hikyuu2/hikyuu_cpp/hikyuu/datetime/TimeDelta.h
2020-05-01 18:49:36 +08:00

312 lines
8.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* TimeDelta.h
*
* Copyright(C) 2019, hikyuu.org
*
* Created on: 2019-12-12
* Author: fasiondog
*/
#pragma once
#ifndef HIKYUU_DATETIME_TIMEDELTA_H
#define HIKYUU_DATETIME_TIMEDELTA_H
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <cstdint>
#include <fmt/format.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#ifndef HKU_API
#define HKU_API
#endif
namespace hku {
namespace bt = boost::posix_time;
namespace bd = boost::gregorian;
/**
* 时长,用于时间计算
* @ingroup DataType
*/
class HKU_API TimeDelta {
public:
/**
* 构造函数
* @note
* <pre>
* 1、总时长范围TimeDetla(-99999999) - TimeDelta(99999999, 23, 59, 59, 999, 999)。
* 2、和 boost::posix_time::time_duration 有所区别time_duration 只要有一个参数为负数,
* 则认为是负时长,而 TimeDelta 则是各参数代表的ticks数之和。
* 3、当为负时长时只有 days() 为负其余各部分hours() ...)均为正数。和 python 的
* datetime.timedelta 行为一致。
* </pre>
* @param days 天数 [-99999999, 99999999]
* @param hours 小时数 [-100000, 100000]
* @param minutes 分钟数 [-100000, 100000]
* @param seconds 秒数 [-8639900, 8639900])
* @param milliseconds 毫秒数 [-86399000000, 86399000000])
* @param microseconds 微秒数 [-86399000000, 86399000000])
*/
explicit TimeDelta(int64_t days = 0, int64_t hours = 0, int64_t minutes = 0,
int64_t seconds = 0, int64_t milliseconds = 0, int64_t microseconds = 0);
/** 通过 boost::posix_time::time_duration 构造 */
explicit TimeDelta(bt::time_duration td);
/** 赋值构造函数 */
TimeDelta(const TimeDelta&) = default;
/** 赋值拷贝函数 */
TimeDelta& operator=(const TimeDelta& other) {
if (this != &other) {
m_duration = other.m_duration;
}
return *this;
}
/** 获取规范化后的天数 */
int64_t days() const;
/** 获取规范化后的小时数 [0, 23] */
int64_t hours() const;
/** 获取规范化后的分钟数 [0, 59] */
int64_t minutes() const;
/** 获取规范化后的秒数 [0, 59] */
int64_t seconds() const;
/** 获取规范化后的毫秒数 [0, 999] */
int64_t milliseconds() const;
/** 获取规范化后的微秒数 [0, 999] */
int64_t microseconds() const;
/** 获取 tick 数,即转换为微秒后的总微秒数 */
int64_t ticks() const {
return m_duration.ticks();
}
/** 返回带小数的总天数 */
double total_days() const {
return double(ticks()) / 86400000000.0;
}
/** 返回带小数的总小时数 */
double total_hours() const {
return double(ticks()) / 3600000000.0;
}
/** 返回带小数的总分钟数 */
double total_minutes() const {
return double(ticks()) / 60000000.0;
}
/** 返回带小数的总秒数 */
double total_seconds() const {
return double(ticks()) / 1000000.0;
}
/** 返回带小数的总毫秒数 */
double total_milliseconds() const {
return double(ticks()) / 1000.0;
}
/** 是否为负时长 */
bool isNegative() const {
return m_duration.is_negative();
}
/** 求绝对值 */
TimeDelta abs() const {
return TimeDelta::fromTicks(std::abs(ticks()));
}
/** 转换为 boost::posix_time::time_duration */
bt::time_duration time_duration() const {
return m_duration;
}
/** 转换为字符串,格式:-1 days hh:mm:ss.000000) */
std::string str() const {
return fmt::format("{} days, {:>02d}:{:>02d}:{:<2.6f}", days(), hours(), minutes(),
seconds() + double(milliseconds() * 1000 + microseconds()) * 0.000001);
}
/** 转换为字符串格式为TimeDelta(days,hours,mins,secs,millisecs,microsecs) */
std::string repr() const {
return fmt::format("TimeDelta({}, {}, {}, {}, {}, {})", days(), hours(), minutes(),
seconds(), milliseconds(), microseconds());
}
/////////////////////////////////////////////////////////////////
//
// 运算符重载TimeDelta 相关运算
//
/////////////////////////////////////////////////////////////////
/** 两个时长相加 */
TimeDelta operator+(TimeDelta td) const {
return TimeDelta(td.m_duration + m_duration);
}
/** 两个时长相减 */
TimeDelta operator-(TimeDelta td) const {
return TimeDelta(m_duration - td.m_duration);
}
/** + 号,返回相同值 */
TimeDelta operator+() const {
return *this;
}
/** - 号, 求负值,相当于 TimeDelta(0) 减自身 */
TimeDelta operator-() const {
return TimeDelta::fromTicks(-ticks());
}
/** 时长乘以系数,结果四舍五入 */
TimeDelta operator*(double p) const;
/**
* 时长除以系数,结果四舍五入。如果除零,将抛出 hku::exception。
* 如果不希望四舍五入,请使用 floorDiv
*/
TimeDelta operator/(double p) const;
/** 两个时长相除,求两者比例。如果除以零时长,将抛出 hku::exception。 */
double operator/(TimeDelta td) const;
/** 地板除,小数点后直接截断 */
TimeDelta floorDiv(double p) const;
/** 两个时长相除求余。如果除以零时长,将抛出 hku::exception。 */
TimeDelta operator%(TimeDelta td) const;
bool operator==(TimeDelta td) const {
return m_duration == td.m_duration;
}
bool operator!=(TimeDelta td) const {
return m_duration != td.m_duration;
}
bool operator>(TimeDelta td) const {
return m_duration > td.m_duration;
}
bool operator<(TimeDelta td) const {
return m_duration < td.m_duration;
}
bool operator>=(TimeDelta td) const {
return m_duration >= td.m_duration;
}
bool operator<=(TimeDelta td) const {
return m_duration <= td.m_duration;
}
/////////////////////////////////////////////////////////////////
//
// 静态成员函数
//
/////////////////////////////////////////////////////////////////
/** 获取能够表达的最小值 TimeDelta(-99999999) */
static TimeDelta min() {
return TimeDelta(-99999999);
}
/** 获取能够表达的最大值 TimeDelta(99999999, 23, 59, 59, 999, 999) */
static TimeDelta max() {
return TimeDelta(99999999, 23, 59, 59, 999, 999);
}
/** 支持的最大 tick 数 */
static int64_t maxTicks() {
return m_max_micro_seconds;
}
/** 支持的最小 tick 数 */
static int64_t minTicks() {
return m_min_micro_seconds;
}
/** 获取表达精度 1 微秒, TimeDelta(0, 0, 0, 0, 0, 1) */
static TimeDelta resolution() {
return TimeDelta(0, 0, 0, 0, 0, 1);
}
/** 从 ticks 创建 */
static TimeDelta fromTicks(int64_t ticks);
private:
bt::time_duration m_duration;
static constexpr const int64_t m_max_micro_seconds = 100000000LL * 24 * 60 * 60 * 1000000 - 1;
static constexpr const int64_t m_min_micro_seconds = -99999999LL * 24 * 60 * 60 * 1000000;
static constexpr const int64_t m_one_day_ticks = 24 * 60 * 60 * 1000000LL;
};
std::ostream& operator<<(std::ostream& out, TimeDelta td);
inline std::ostream& operator<<(std::ostream& out, TimeDelta td) {
out << td.str();
return out;
}
/**
* TimeDelta 快捷创建函数
* @param days 天数 [-99999999, 99999999]
* @ingroup DataType
*/
TimeDelta Days(int64_t days);
inline TimeDelta Days(int64_t days) {
return TimeDelta(days);
}
/**
* TimeDelta 快捷创建函数
* @param hours 小时数
* @ingroup DataType
*/
TimeDelta HKU_API Hours(int64_t hours);
/**
* TimeDelta 快捷创建函数
* @param mins 分钟数
* @ingroup DataType
*/
TimeDelta HKU_API Minutes(int64_t mins);
/**
* TimeDelta 快捷创建函数
* @param secs 秒数
* @ingroup DataType
*/
TimeDelta HKU_API Seconds(int64_t secs);
/**
* TimeDelta 快捷创建函数
* @param milliseconds 毫秒数
* @ingroup DataType
*/
TimeDelta HKU_API Milliseconds(int64_t milliseconds);
/**
* TimeDelta 快捷创建函数
* @param microsecs 微秒数
* @ingroup DataType
*/
TimeDelta Microseconds(int64_t microsecs);
inline TimeDelta Microseconds(int64_t microsecs) {
return TimeDelta::fromTicks(microsecs);
}
} /* namespace hku */
#endif /* HIKYUU_DATETIME_TIMEDELTA_H */