an-tao / trantor

a non-blocking I/O tcp network lib based on c++14/17
Other
398 stars 134 forks source link

More clang format options #337

Closed hks2002 closed 2 months ago

hks2002 commented 5 months ago

Align:

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

Include Group and Sort

image

hwc0919 commented 5 months ago

I don't think we need this...

hks2002 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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.