blob: 546bea0ef25821da6f6228ab401aac6d593a2617 [file] [log] [blame]
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Microsoft Corporation
*
* -=- Robust Distributed System Nucleus (rDSN) -=-
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
// IWYU pragma: no_include <bits/types/struct_tm.h>
#include <stdint.h>
#include <time.h>
#include <chrono>
#include <cstdio>
#include <string>
#include "absl/strings/string_view.h"
#include "runtime/api_layer1.h"
#include "utils/fmt_logging.h"
#include "utils/ports.h"
namespace dsn {
namespace utils {
static struct tm *get_localtime(uint64_t ts_ms, struct tm *tm_buf)
{
auto t = (time_t)(ts_ms / 1000);
return localtime_r(&t, tm_buf);
}
// Get time string, which format is yyyy-MM-dd hh:mm:ss.SSS
// NOTE: using char* as output is usually unsafe, remember to initialize its memory as zero before
// calling 'time_ms_to_string'. Please use std::string as the output argument as long as it's
// possible.
extern void time_ms_to_string(uint64_t ts_ms, char *str);
extern void time_ms_to_string(uint64_t ts_ms, std::string &str);
// Get time string, which format is yyyyMMdd_hhmmss_SSS
extern void time_ms_to_sequent_string(uint64_t ts_ms, std::string &str);
// get date string with format of 'yyyy-MM-dd' from given timestamp
inline void time_ms_to_date(uint64_t ts_ms, char *str, int len)
{
struct tm tmp;
strftime(str, len, "%Y-%m-%d", get_localtime(ts_ms, &tmp));
}
// get date string with format of 'yyyy-MM-dd hh:mm:ss' from given timestamp(ms)
inline void time_ms_to_date_time(uint64_t ts_ms, char *str, int len)
{
struct tm tmp;
strftime(str, len, "%Y-%m-%d %H:%M:%S", get_localtime(ts_ms, &tmp));
}
// get date string with format of 'yyyy-MM-dd hh:mm:ss' from given timestamp(s)
inline std::string time_s_to_date_time(uint64_t unix_seconds)
{
char buffer[128];
utils::time_ms_to_date_time(unix_seconds * 1000, buffer, 128);
return std::string(buffer);
}
// parse hour/min/sec from the given timestamp
inline void time_ms_to_date_time(uint64_t ts_ms, int32_t &hour, int32_t &min, int32_t &sec)
{
struct tm tmp;
auto ret = get_localtime(ts_ms, &tmp);
hour = ret->tm_hour;
min = ret->tm_min;
sec = ret->tm_sec;
}
// get current physical timestamp in ns
inline uint64_t get_current_physical_time_ns()
{
auto now = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
}
// get current physical timestamp in s
inline uint64_t get_current_physical_time_s() { return get_current_physical_time_ns() * 1e-9; }
// get unix timestamp of today's zero o'clock.
// eg. `1525881600` returned when called on May 10, 2018, CST
inline int64_t get_unix_sec_today_midnight()
{
time_t t = time(nullptr);
struct tm tmp;
auto ret = localtime_r(&t, &tmp);
ret->tm_hour = 0;
ret->tm_min = 0;
ret->tm_sec = 0;
return static_cast<int64_t>(mktime(ret));
}
// `hh:mm` (range in [00:00, 23:59]) to seconds since 00:00:00
// eg. `01:00` => `3600`
// Return: -1 when invalid
inline int hh_mm_to_seconds(absl::string_view hhmm)
{
int hour = 0, min = 0, sec = -1;
if (::sscanf(hhmm.data(), "%d:%d", &hour, &min) == 2 && (0 <= hour && hour <= 23) &&
(0 <= min && min <= 59)) {
sec = 3600 * hour + 60 * min;
}
return sec;
}
// local time `hh:mm` to unix timestamp.
// eg. `18:10` => `1525947000` when called on May 10, 2018, CST
// Return: -1 when invalid
inline int64_t hh_mm_today_to_unix_sec(absl::string_view hhmm_of_day)
{
int sec_of_day = hh_mm_to_seconds(hhmm_of_day);
if (sec_of_day == -1) {
return -1;
}
return get_unix_sec_today_midnight() + sec_of_day;
}
class chronograph
{
public:
chronograph() : chronograph(dsn_now_ns()) {}
chronograph(uint64_t start_time_ns) : _start_time_ns(start_time_ns) {}
~chronograph() = default;
inline void reset_start_time() { _start_time_ns = dsn_now_ns(); }
inline uint64_t duration_ns() const
{
auto now = dsn_now_ns();
CHECK_GE(now, _start_time_ns);
return now - _start_time_ns;
}
private:
uint64_t _start_time_ns;
DISALLOW_COPY_AND_ASSIGN(chronograph);
};
} // namespace utils
} // namespace dsn