Closed hks2002 closed 2 months ago
I don't think we need this...
Let's see the difference:
Before:
/**
*
* @file Date.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/exports.h>
#include <stdint.h>
#include <string>
#define MICRO_SECONDS_PRE_SEC 1000000LL
namespace trantor
{
/**
* @brief This class represents a time point.
*
*/
class TRANTOR_EXPORT Date
{
public:
Date() : microSecondsSinceEpoch_(0){};
/**
* @brief Construct a new Date instance.
*
* @param microSec The microseconds from 1970-01-01 00:00:00.
*/
explicit Date(int64_t microSec) : microSecondsSinceEpoch_(microSec){};
/**
* @brief Construct a new Date instance.
*
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
* @param microSecond
*/
Date(unsigned int year,
unsigned int month,
unsigned int day,
unsigned int hour = 0,
unsigned int minute = 0,
unsigned int second = 0,
unsigned int microSecond = 0);
/**
* @brief Create a Date object that represents the current time.
*
* @return const Date
*/
static const Date date();
/**
* @brief Same as the date() method.
*
* @return const Date
*/
static const Date now()
{
return Date::date();
}
static int64_t timezoneOffset()
{
static int64_t offset = -(
Date::fromDbStringLocal("1970-01-03 00:00:00").secondsSinceEpoch() -
2LL * 3600LL * 24LL);
return offset;
}
/**
* @brief Return a new Date instance that represents the time after some
* seconds from *this.
*
* @param second
* @return const Date
*/
const Date after(double second) const;
/**
* @brief Return a new Date instance that equals to *this, but with zero
* microseconds.
*
* @return const Date
*/
const Date roundSecond() const;
/// Create a Date object equal to * this, but numbers of hours, minutes,
/// seconds and microseconds are zero.
/**
* @brief Return a new Date instance that equals to * this, but with zero
* hours, minutes, seconds and microseconds.
*
* @return const Date
*/
const Date roundDay() const;
~Date(){};
/**
* @brief Return true if the time point is equal to another.
*
*/
bool operator==(const Date &date) const
{
return microSecondsSinceEpoch_ == date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not equal to another.
*
*/
bool operator!=(const Date &date) const
{
return microSecondsSinceEpoch_ != date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is earlier than another.
*
*/
bool operator<(const Date &date) const
{
return microSecondsSinceEpoch_ < date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is later than another.
*
*/
bool operator>(const Date &date) const
{
return microSecondsSinceEpoch_ > date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not earlier than another.
*
*/
bool operator>=(const Date &date) const
{
return microSecondsSinceEpoch_ >= date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not later than another.
*
*/
bool operator<=(const Date &date) const
{
return microSecondsSinceEpoch_ <= date.microSecondsSinceEpoch_;
}
/**
* @brief Get the number of milliseconds since 1970-01-01 00:00.
*
* @return int64_t
*/
int64_t microSecondsSinceEpoch() const
{
return microSecondsSinceEpoch_;
}
/**
* @brief Get the number of seconds since 1970-01-01 00:00.
*
* @return int64_t
*/
int64_t secondsSinceEpoch() const
{
return microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC;
}
/**
* @brief Get the tm struct for the time point.
*
* @return struct tm
*/
struct tm tmStruct() const;
/**
* @brief Generate a UTC time string
* @param showMicroseconds whether the microseconds are returned.
* @note Examples:
* - "20180101 10:10:25" if the @p showMicroseconds is false
* - "20180101 10:10:25:102414" if the @p showMicroseconds is true
*/
std::string toFormattedString(bool showMicroseconds) const;
/* clang-format off */
/**
* @brief Generate a UTC time string formatted by the @p fmtStr
* @param fmtStr is the format string for the function strftime()
* @param showMicroseconds whether the microseconds are returned.
* @note Examples:
* - "2018-01-01 10:10:25" if the @p fmtStr is "%Y-%m-%d %H:%M:%S" and the
* @p showMicroseconds is false
* - "2018-01-01 10:10:25:102414" if the @p fmtStr is "%Y-%m-%d %H:%M:%S"
* and the @p showMicroseconds is true
* @deprecated Replaced by toCustomFormattedString
*/
[[deprecated("Replaced by toCustomFormattedString")]]
std::string toCustomedFormattedString(const std::string &fmtStr,
bool showMicroseconds = false) const
{
return toCustomFormattedString(fmtStr, showMicroseconds);
};
/* clang-format on */
/**
* @brief Generate a UTC time string formatted by the @p fmtStr
* @param fmtStr is the format string for the function strftime()
* @param showMicroseconds whether the microseconds are returned.
* @note Examples:
* - "2018-01-01 10:10:25" if the @p fmtStr is "%Y-%m-%d %H:%M:%S" and the
* @p showMicroseconds is false
* - "2018-01-01 10:10:25:102414" if the @p fmtStr is "%Y-%m-%d %H:%M:%S"
* and the @p showMicroseconds is true
*/
std::string toCustomFormattedString(const std::string &fmtStr,
bool showMicroseconds = false) const;
/**
* @brief Generate a local time zone string, the format of the string is
* same as the method toFormattedString
*
* @param showMicroseconds
* @return std::string
*/
std::string toFormattedStringLocal(bool showMicroseconds) const;
/* clang-format off */
/**
* @brief Generate a local time zone string formatted by the @p fmtStr
*
* @param fmtStr
* @param showMicroseconds
* @return std::string
* @deprecated Replaced by toCustomFormattedString
*/
[[deprecated("Replaced by toCustomFormattedStringLocal")]]
std::string toCustomedFormattedStringLocal(const std::string &fmtStr,
bool showMicroseconds = false) const
{
return toCustomFormattedStringLocal(fmtStr, showMicroseconds);
}
/* clang-format on */
/**
* @brief Generate a local time zone string formatted by the @p fmtStr
*
* @param fmtStr
* @param showMicroseconds
* @return std::string
*/
std::string toCustomFormattedStringLocal(
const std::string &fmtStr,
bool showMicroseconds = false) const;
/**
* @brief Generate a local time zone string for database.
* @note Examples:
* - "2018-01-01" if hours, minutes, seconds and microseconds are zero
* - "2018-01-01 10:10:25" if the microsecond is zero
* - "2018-01-01 10:10:25:102414" if the microsecond is not zero
*/
std::string toDbStringLocal() const;
/**
* @brief Generate a UTC time string for database.
*/
std::string toDbString() const;
/**
* @brief From DB string to trantor local time zone.
*
* Inverse of toDbStringLocal()
*/
static Date fromDbStringLocal(const std::string &datetime);
/**
* @brief From DB string to trantor UTC time.
*
* Inverse of toDbString()
*/
static Date fromDbString(const std::string &datetime);
/* clang-format off */
/**
* @brief Generate a UTC time string.
*
* @param fmtStr The format string.
* @param str The string buffer for the generated time string.
* @param len The length of the string buffer.
* @deprecated Replaced by toCustomFormattedString
*/
[[deprecated("Replaced by toCustomFormattedString")]]
void toCustomedFormattedString(const std::string &fmtStr,
char *str,
size_t len) const
{
toCustomFormattedString(fmtStr, str, len);
}
/* clang-format on */
/**
* @brief Generate a UTC time string.
*
* @param fmtStr The format string.
* @param str The string buffer for the generated time string.
* @param len The length of the string buffer.
*/
void toCustomFormattedString(const std::string &fmtStr,
char *str,
size_t len) const; // UTC
/**
* @brief Return true if the time point is in a same second as another.
*
* @param date
* @return true
* @return false
*/
bool isSameSecond(const Date &date) const
{
return microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC ==
date.microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC;
}
/**
* @brief Swap the time point with another.
*
* @param that
*/
void swap(Date &that)
{
std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
}
private:
int64_t microSecondsSinceEpoch_{0};
};
} // namespace trantor
/**
*
* Date.cc
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#include "Date.h"
#include "Funcs.h"
#ifndef _WIN32
#include <sys/time.h>
#endif
#include <cstdlib>
#include <iostream>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#include <time.h>
#endif
namespace trantor
{
#ifdef _WIN32
int gettimeofday(timeval *tp, void *tzp)
{
time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm.tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = static_cast<long>(clock);
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
#endif
const Date Date::date()
{
#ifndef _WIN32
struct timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec);
#else
timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec);
#endif
}
const Date Date::after(double second) const
{
return Date(static_cast<int64_t>(microSecondsSinceEpoch_ +
second * MICRO_SECONDS_PRE_SEC));
}
const Date Date::roundSecond() const
{
return Date(microSecondsSinceEpoch_ -
(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC));
}
const Date Date::roundDay() const
{
struct tm t;
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
#ifndef _WIN32
localtime_r(&seconds, &t);
#else
localtime_s(&t, &seconds);
#endif
t.tm_hour = 0;
t.tm_min = 0;
t.tm_sec = 0;
return Date(mktime(&t) * MICRO_SECONDS_PRE_SEC);
}
struct tm Date::tmStruct() const
{
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
return tm_time;
}
std::string Date::toFormattedString(bool showMicroseconds) const
{
// std::cout<<"toFormattedString"<<std::endl;
char buf[128] = {0};
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
if (showMicroseconds)
{
int microseconds =
static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
}
else
{
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
return buf;
}
std::string Date::toCustomFormattedString(const std::string &fmtStr,
bool showMicroseconds) const
{
char buf[256] = {0};
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
strftime(buf, sizeof(buf), fmtStr.c_str(), &tm_time);
if (!showMicroseconds)
return std::string(buf);
char decimals[12] = {0};
int microseconds =
static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(decimals, sizeof(decimals), ".%06d", microseconds);
return std::string(buf) + decimals;
}
void Date::toCustomFormattedString(const std::string &fmtStr,
char *str,
size_t len) const
{
// not safe
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
strftime(str, len, fmtStr.c_str(), &tm_time);
}
std::string Date::toFormattedStringLocal(bool showMicroseconds) const
{
// std::cout<<"toFormattedString"<<std::endl;
char buf[128] = {0};
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
if (showMicroseconds)
{
int microseconds =
static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
}
else
{
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
return buf;
}
std::string Date::toDbStringLocal() const
{
char buf[128] = {0};
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
bool showMicroseconds =
(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC != 0);
if (showMicroseconds)
{
int microseconds =
static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d-%02d-%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
}
else
{
if (*this == roundDay())
{
snprintf(buf,
sizeof(buf),
"%4d-%02d-%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday);
}
else
{
snprintf(buf,
sizeof(buf),
"%4d-%02d-%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
}
return buf;
}
std::string Date::toDbString() const
{
return after(static_cast<double>(-timezoneOffset())).toDbStringLocal();
}
Date Date::fromDbStringLocal(const std::string &datetime)
{
unsigned int year = {0}, month = {0}, day = {0}, hour = {0}, minute = {0},
second = {0}, microSecond = {0};
std::vector<std::string> &&v = splitString(datetime, " ");
if (2 == v.size())
{
// date
std::vector<std::string> date = splitString(v[0], "-");
if (3 == date.size())
{
year = std::stol(date[0]);
month = std::stol(date[1]);
day = std::stol(date[2]);
std::vector<std::string> time = splitString(v[1], ":");
if (2 < time.size())
{
hour = std::stol(time[0]);
minute = std::stol(time[1]);
auto seconds = splitString(time[2], ".");
second = std::stol(seconds[0]);
if (1 < seconds.size())
{
if (seconds[1].length() > 6)
{
seconds[1].resize(6);
}
else if (seconds[1].length() < 6)
{
seconds[1].append(6 - seconds[1].length(), '0');
}
microSecond = std::stol(seconds[1]);
}
}
}
}
return trantor::Date(year, month, day, hour, minute, second, microSecond);
}
Date Date::fromDbString(const std::string &datetime)
{
return fromDbStringLocal(datetime).after(
static_cast<double>(timezoneOffset()));
}
std::string Date::toCustomFormattedStringLocal(const std::string &fmtStr,
bool showMicroseconds) const
{
char buf[256] = {0};
time_t seconds =
static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
strftime(buf, sizeof(buf), fmtStr.c_str(), &tm_time);
if (!showMicroseconds)
return std::string(buf);
char decimals[12] = {0};
int microseconds =
static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(decimals, sizeof(decimals), ".%06d", microseconds);
return std::string(buf) + decimals;
}
Date::Date(unsigned int year,
unsigned int month,
unsigned int day,
unsigned int hour,
unsigned int minute,
unsigned int second,
unsigned int microSecond)
{
struct tm tm;
memset(&tm, 0, sizeof(tm));
tm.tm_isdst = -1;
time_t epoch;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
epoch = mktime(&tm);
microSecondsSinceEpoch_ =
static_cast<int64_t>(epoch) * MICRO_SECONDS_PRE_SEC + microSecond;
}
} // namespace trantor
and After:
/**
*
* @file Date.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#ifndef TRANTOR_DATE_H
#define TRANTOR_DATE_H
#include "trantor/exports.h"
#include <cstdint>
#include <string_view>
namespace trantor {
/**
* @brief This class represents a time point.
*
*/
class TRANTOR_EXPORT Date {
public:
Date();
explicit Date(int64_t microSec);
Date(unsigned int year,
unsigned int month,
unsigned int day,
unsigned int hour = 0,
unsigned int minute = 0,
unsigned int second = 0,
unsigned int microSecond = 0);
static const Date date();
static const Date now();
static Date fromDbString(std::string_view datetime);
static Date fromDbStringLocal(std::string_view datetime);
static int64_t timezoneOffset();
int64_t microSecondsSinceEpoch() const;
int64_t secondsSinceEpoch() const;
bool isSameSecond(const Date &date) const;
bool isSameSecond(Date &&date) const;
void swap(Date &that);
const Date after(double second) const;
const Date roundSecond() const;
const Date roundDay() const;
std::string toDbString() const;
std::string toDbStringLocal() const;
std::string toFormattedString(bool showMicroseconds) const;
std::string toFormattedStringLocal(bool showMicroseconds) const;
std::string toCustomFormattedString(std::string_view fmtStr, bool showMicroseconds = false) const;
std::string toCustomFormattedStringLocal(std::string_view fmtStr, bool showMicroseconds = false) const;
void toCustomFormattedString(std::string_view fmtStr, char *str, size_t len) const; // UTC
// Comparators
bool operator==(const Date &date) const;
bool operator!=(const Date &date) const;
bool operator<(const Date &date) const;
bool operator>(const Date &date) const;
bool operator>=(const Date &date) const;
bool operator<=(const Date &date) const;
private:
struct tm tmStruct() const;
int64_t microSecondsSinceEpoch_{0};
};
} // namespace trantor
#endif // TRANTOR_DATE_H
/**
*
* Date.cc
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#include "Date.h"
#include "StringUtils.h"
#ifndef _WIN32
#include <sys/time.h>
#else
#include <corecrt.h>
#include <time.h>
#include <winsock2.h>
#endif
#include <cstdint>
#include <cstring>
#include <stdio.h>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
namespace trantor {
/**
* @brief define microseconds per second
*
*/
const int64_t MICRO_SECONDS_PRE_SEC = 1000000LL;
/**
* @brief Construct a new Date instance.
*/
Date::Date() : microSecondsSinceEpoch_(0){};
/**
* @brief Construct a new Date instance.
*
* @param microSec The microseconds from 1970-01-01 00:00:00.
*/
Date::Date(int64_t microSec) : microSecondsSinceEpoch_(microSec){};
/**
* @brief Constructor for Date class that initializes the date and time based on the provided parameters.
*
* @param year The year value for the date, such as 2018
* @param month The month value for the date, range 1-12
* @param day The day value for the date, range 1-31
* @param hour The hour value for the time, range 0-23
* @param minute The minute value for the time, range 0-59
* @param second The second value for the time, range 0-59
* @param microSecond The microsecond value for the time
*/
Date::Date(unsigned int year,
unsigned int month,
unsigned int day,
unsigned int hour,
unsigned int minute,
unsigned int second,
unsigned int microSecond) {
struct tm tm;
memset(&tm, 0, sizeof(tm));
tm.tm_isdst = -1;
time_t epoch;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
epoch = mktime(&tm);
microSecondsSinceEpoch_ = static_cast<int64_t>(epoch) * MICRO_SECONDS_PRE_SEC + microSecond;
}
/**
* @brief From DB string to trantor UTC time.
*
* Inverse of toDbString()
*/
Date Date::fromDbString(std::string_view datetime) {
return fromDbStringLocal(datetime).after(static_cast<double>(timezoneOffset()));
}
/**
* @brief From DB string to trantor local time zone.
*
* Inverse of toDbStringLocal()
*/
Date Date::fromDbStringLocal(std::string_view datetime) {
unsigned int year = {0}, month = {0}, day = {0}, hour = {0}, minute = {0}, second = {0}, microSecond = {0};
std::vector<std::string> &&v = trantor::utils::splitString(datetime, " ");
if (2 == v.size()) {
// date
std::vector<std::string> date = trantor::utils::splitString(v[0], "-");
if (3 == date.size()) {
year = std::stol(date[0]);
month = std::stol(date[1]);
day = std::stol(date[2]);
// time
std::vector<std::string> time = trantor::utils::splitString(v[1], ":");
if (2 < time.size()) {
hour = std::stol(time[0]);
minute = std::stol(time[1]);
auto seconds = trantor::utils::splitString(time[2], ".");
second = std::stol(seconds[0]);
if (1 < seconds.size()) {
if (seconds[1].length() > 6) {
seconds[1].resize(6);
} else if (seconds[1].length() < 6) {
seconds[1].append(6 - seconds[1].length(), '0');
}
microSecond = std::stol(seconds[1]);
}
}
}
}
return Date(year, month, day, hour, minute, second, microSecond);
}
/**
* @brief Returns the timezone offset for the Date.
*
* @return the timezone offset
*/
int64_t Date::timezoneOffset() {
static int64_t offset = -(Date(1970, 1, 3).secondsSinceEpoch() - 2LL * 3600LL * 24LL);
return offset;
}
/**
* @brief Get the tm struct for the time point.
*
* @return struct tm
*/
struct tm Date::tmStruct() const {
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
return tm_time;
}
#ifdef _WIN32
/**
* @brief Retrieves the current time and timezone information.
*
* @param tp pointer to a timeval structure to store the time
* @param tzp pointer to timezone information (not used in this implementation)
*
* @return 0 indicating success
*
* @throws None
*/
int gettimeofday(timeval *tp, void *tzp) {
time_t clock;
struct tm tm;
SYSTEMTIME wtm;
GetLocalTime(&wtm);
tm.tm_year = wtm.wYear - 1900;
tm.tm_mon = wtm.wMonth - 1;
tm.tm_mday = wtm.wDay;
tm.tm_hour = wtm.wHour;
tm.tm_min = wtm.wMinute;
tm.tm_sec = wtm.wSecond;
tm.tm_isdst = -1;
clock = mktime(&tm);
tp->tv_sec = static_cast<long>(clock);
tp->tv_usec = wtm.wMilliseconds * 1000;
return (0);
}
#endif
/**
* @brief Create a Date object that represents the current time.
*
* @return const Date
*/
const Date Date::date() {
#ifndef _WIN32
struct timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec);
#else
timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return Date(seconds * MICRO_SECONDS_PRE_SEC + tv.tv_usec);
#endif
}
/**
* @brief Same as the date() method.
*
* @return const Date
*/
const Date Date::now() {
return Date::date();
}
/**
* @brief Get the number of milliseconds since 1970-01-01 00:00.
*
* @return int64_t
*/
int64_t Date::microSecondsSinceEpoch() const {
return microSecondsSinceEpoch_;
}
/**
* @brief Get the number of seconds since 1970-01-01 00:00.
*
* @return int64_t
*/
int64_t Date::secondsSinceEpoch() const {
return microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC;
}
/**
* @brief Return true if the time point is in a same second as another.
*
* @param date
* @return true
* @return false
*/
bool Date::isSameSecond(const Date &date) const {
return microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC == date.microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC;
}
/**
* @brief Return true if the time point is in a same second as another.
*
* @param date
* @return true
* @return false
*/
bool Date::isSameSecond(Date &&date) const {
return microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC == date.microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC;
}
/**
* @brief Swap the time point with another.
*
* @param that
*/
void Date::swap(Date &that) {
std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
}
/**
* @brief Return a new Date instance that represents the time after some seconds from *this.
*
* @param second
* @return const Date
*/
const Date Date::after(double second) const {
return Date(static_cast<int64_t>(microSecondsSinceEpoch_ + second * MICRO_SECONDS_PRE_SEC));
}
/**
* @brief Return a new Date instance that equals to *this, but with zero
* microseconds.
*
* @return const Date
*/
const Date Date::roundSecond() const {
return Date(microSecondsSinceEpoch_ - (microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC));
}
/**
* @brief Return a new Date instance that equals to * this, but with zero
* hours, minutes, seconds and microseconds.
*
* @return const Date
*/
const Date Date::roundDay() const {
struct tm t;
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
#ifndef _WIN32
localtime_r(&seconds, &t);
#else
localtime_s(&t, &seconds);
#endif
t.tm_hour = 0;
t.tm_min = 0;
t.tm_sec = 0;
return Date(mktime(&t) * MICRO_SECONDS_PRE_SEC);
}
/**
* @brief Generate a UTC time string for database.
*/
std::string Date::toDbString() const {
return after(static_cast<double>(-timezoneOffset())).toDbStringLocal();
}
/**
* @brief Generate a local time zone string for database.
* @note Examples:
* - "2018-01-01" if hours, minutes, seconds and microseconds are zero
* - "2018-01-01 10:10:25" if the microsecond is zero
* - "2018-01-01 10:10:25:102414" if the microsecond is not zero
*/
std::string Date::toDbStringLocal() const {
char buf[128] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
bool showMicroseconds = (microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC != 0);
if (showMicroseconds) {
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d-%02d-%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
} else {
if (*this == roundDay()) {
snprintf(buf, sizeof(buf), "%4d-%02d-%02d", tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday);
} else {
snprintf(buf,
sizeof(buf),
"%4d-%02d-%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
}
return buf;
}
/**
* @brief Generate a UTC time string.
* Converts the date to a formatted string with the option to include microseconds.
*
* @param showMicroseconds boolean flag indicating whether to include microseconds in the formatted string
*
* @return formatted string representing the date
* @note Examples:
* - "20180101 10:10:25" if the @p showMicroseconds is false
* - "20180101 10:10:25:102414" if the @p showMicroseconds is true
* @throws None
*/
std::string Date::toFormattedString(bool showMicroseconds) const {
// std::cout<<"toFormattedString"<<std::endl;
char buf[128] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
if (showMicroseconds) {
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
} else {
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
return buf;
}
/**
* @brief Generate a local time zone string, the format of the string is
* same as the method toFormattedString
*
* @param showMicroseconds
* @return std::string
*/
std::string Date::toFormattedStringLocal(bool showMicroseconds) const {
// std::cout<<"toFormattedString"<<std::endl;
char buf[128] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
if (showMicroseconds) {
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec,
microseconds);
} else {
snprintf(buf,
sizeof(buf),
"%4d%02d%02d %02d:%02d:%02d",
tm_time.tm_year + 1900,
tm_time.tm_mon + 1,
tm_time.tm_mday,
tm_time.tm_hour,
tm_time.tm_min,
tm_time.tm_sec);
}
return buf;
}
/**
* @brief Generate a UTC time string formatted by the @p fmtStr
* @param fmtStr is the format string for the function strftime()
* @param showMicroseconds whether the microseconds are returned.
* @note Examples:
* - "2018-01-01 10:10:25" if the @p fmtStr is "%Y-%m-%d %H:%M:%S" and the
* @p showMicroseconds is false
* - "2018-01-01 10:10:25:102414" if the @p fmtStr is "%Y-%m-%d %H:%M:%S"
* and the @p showMicroseconds is true
*/
std::string Date::toCustomFormattedString(std::string_view fmtStr, bool showMicroseconds) const {
char buf[256] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
strftime(buf, sizeof(buf), fmtStr.data(), &tm_time);
if (!showMicroseconds) return std::string(buf);
char decimals[12] = {0};
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(decimals, sizeof(decimals), ".%06d", microseconds);
return std::string(buf) + decimals;
}
/**
* @brief Generate a local time zone string formatted by the @p fmtStr
*
* @param fmtStr
* @param showMicroseconds
* @return std::string
*/
std::string Date::toCustomFormattedStringLocal(std::string_view fmtStr, bool showMicroseconds) const {
char buf[256] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
localtime_r(&seconds, &tm_time);
#else
localtime_s(&tm_time, &seconds);
#endif
strftime(buf, sizeof(buf), fmtStr.data(), &tm_time);
if (!showMicroseconds) return std::string(buf);
char decimals[12] = {0};
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % MICRO_SECONDS_PRE_SEC);
snprintf(decimals, sizeof(decimals), ".%06d", microseconds);
return std::string(buf) + decimals;
}
/**
* @brief Generate a UTC time string.
*
* @param fmtStr The format string.
* @param str The string buffer for the generated time string.
* @param len The length of the string buffer.
*/
void Date::toCustomFormattedString(std::string_view fmtStr, char *str, size_t len) const {
// not safe
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / MICRO_SECONDS_PRE_SEC);
struct tm tm_time;
#ifndef _WIN32
gmtime_r(&seconds, &tm_time);
#else
gmtime_s(&tm_time, &seconds);
#endif
strftime(str, len, fmtStr.data(), &tm_time);
}
/**
* @brief Return true if the time point is equal to another.
*
*/
bool Date::operator==(const Date &date) const {
return microSecondsSinceEpoch_ == date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not equal to another.
*
*/
bool Date::operator!=(const Date &date) const {
return microSecondsSinceEpoch_ != date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is earlier than another.
*
*/
bool Date::operator<(const Date &date) const {
return microSecondsSinceEpoch_ < date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is later than another.
*
*/
bool Date::operator>(const Date &date) const {
return microSecondsSinceEpoch_ > date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not earlier than another.
*
*/
bool Date::operator>=(const Date &date) const {
return microSecondsSinceEpoch_ >= date.microSecondsSinceEpoch_;
}
/**
* @brief Return true if the time point is not later than another.
*
*/
bool Date::operator<=(const Date &date) const {
return microSecondsSinceEpoch_ <= date.microSecondsSinceEpoch_;
}
} // namespace trantor
I am tring to do some codes moving, to let codes became very easy to read and understand. It's friendly to the learners and a new contributor before familiar to all trantor source.
We really appreciate your effort.
However we could not agree on this change.
I am tring to do some codes moving, to let codes became very easy to read and understand.
As a matter of fact, code style is good is a very subjective thing, you should at least prove the new style is better. It's hard for me to believe that the new format make the codes easier to read.
I don't think the same-align thing works in all circumstances. When define macros or enums, it is good, but in variable definitions, I think it's bad. For me, the extra spaces really blocks me from reading the code continuously.
Moreover, none of the popular c++ code styles (LLVM、Google、Chromium、Mozilla、WebKit) use this alignment style.
I suggest you put your effort on improving documents of drogon or trantor, or refactoring poor designed code modules. That will be more effective for your goal.
I agree, there’s enough important things to do, and open tickets that could be worked on, no need to waste time on code style discussions.
Align:
Include Group and Sort