#pragma once
#include <trantor/exports.h>
#include <stdint.h>
#include <string>
namespace trantor
{
class TRANTOR_EXPORT Date
{
  public:
    Date() : microSecondsSinceEpoch_(0){};
    explicit Date(int64_t microSec) : microSecondsSinceEpoch_(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()
    {
        return Date::date();
    }
    static int64_t timezoneOffset();
    const Date after(double second) const;
    const Date roundSecond() const;
    const Date roundDay() const;
    ~Date(){};
    bool operator==(const Date &date) const
    {
        return microSecondsSinceEpoch_ == date.microSecondsSinceEpoch_;
    }
    bool operator!=(const Date &date) const
    {
        return microSecondsSinceEpoch_ != date.microSecondsSinceEpoch_;
    }
    bool operator<(const Date &date) const
    {
        return microSecondsSinceEpoch_ < date.microSecondsSinceEpoch_;
    }
    bool operator>(const Date &date) const
    {
        return microSecondsSinceEpoch_ > date.microSecondsSinceEpoch_;
    }
    bool operator>=(const Date &date) const
    {
        return microSecondsSinceEpoch_ >= date.microSecondsSinceEpoch_;
    }
    bool operator<=(const Date &date) const
    {
        return microSecondsSinceEpoch_ <= date.microSecondsSinceEpoch_;
    }
    int64_t microSecondsSinceEpoch() const
    {
        return microSecondsSinceEpoch_;
    }
    int64_t secondsSinceEpoch() const
    {
        return microSecondsSinceEpoch_ / MICRO_SECONDS_PER_SEC;
    }
    struct tm tmStruct() const;
    std::string toFormattedString(bool showMicroseconds) const;
    [[deprecated("Replaced by toCustomFormattedString")]] 
    std::string toCustomedFormattedString(const std::string &fmtStr,
                                          bool showMicroseconds = false) const
    {
        return toCustomFormattedString(fmtStr, showMicroseconds);
    };
    std::string toCustomFormattedString(const std::string &fmtStr,
                                        bool showMicroseconds = false) const;
    std::string toFormattedStringLocal(bool showMicroseconds) const;
    [[deprecated("Replaced by toCustomFormattedStringLocal")]]
    std::string toCustomedFormattedStringLocal(const std::string &fmtStr,
                                               bool showMicroseconds = false) const
    {
        return toCustomFormattedStringLocal(fmtStr, showMicroseconds);
    }
    std::string toCustomFormattedStringLocal(
        const std::string &fmtStr,
        bool showMicroseconds = false) const;
    std::string toDbStringLocal() const;
    std::string toDbString() const;
    static Date fromDbStringLocal(const std::string &datetime);
    static Date fromDbString(const std::string &datetime);
    static Date fromISOString(const std::string &datetime);
    [[deprecated("Replaced by toCustomFormattedString")]]
    void toCustomedFormattedString(const std::string &fmtStr,
                                   char *str,
                                   size_t len) const
    {
        toCustomFormattedString(fmtStr, str, len);
    }
    void toCustomFormattedString(const std::string &fmtStr,
                                 char *str,
                                 size_t len) const;  
    bool isSameSecond(const Date &date) const
    {
        return microSecondsSinceEpoch_ / MICRO_SECONDS_PER_SEC ==
               date.microSecondsSinceEpoch_ / MICRO_SECONDS_PER_SEC;
    }
    void swap(Date &that)
    {
        std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
    }
    static constexpr long MICRO_SECONDS_PER_SEC = 1000000LL;
  private:
    int64_t microSecondsSinceEpoch_{0};
};
}  