Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More clang format options #337

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

hks2002
Copy link
Contributor

@hks2002 hks2002 commented May 22, 2024

Align:

image
image
image
image
image
image
image
image
image
image
image
image

Include Group and Sort

image

@hwc0919
Copy link
Collaborator

hwc0919 commented May 22, 2024

I don't think we need this...

@hks2002
Copy link
Contributor Author

hks2002 commented May 22, 2024

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

@hks2002
Copy link
Contributor Author

hks2002 commented May 22, 2024

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

@hks2002
Copy link
Contributor Author

hks2002 commented May 22, 2024

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.

@hwc0919
Copy link
Collaborator

hwc0919 commented May 22, 2024

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.

@rbugajewski
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants