9 Star 31 Fork 22

10km/common_source_cpp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
date_utilits.h 13.54 KB
一键复制 编辑 原始数据 按行查看 历史
/*
* date_utilits.h
*
* Created on: 2021年9月22日
* Author: guyadong
*/
#ifndef COMMON_SOURCE_CPP_DATE_UTILITS_H_
#define COMMON_SOURCE_CPP_DATE_UTILITS_H_
#include <chrono>
#include <ctime>
#include <string>
#include <iostream>
#include "date/date.h"
#include <iomanip>
#include <regex>
#include <stdint.h>
namespace date{
/** 系统时间(毫秒) */
using time_mills = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
template <class CharT, class Traits, class Alloc, class Duration>
auto
format(const std::basic_string<CharT, Traits, Alloc>& fmt, const sys_time<Duration>& tp, const std::string& abbrev = { "UTC" },
const std::chrono::seconds& offset_sec = std::chrono::seconds(0))
-> decltype(to_stream(std::declval<std::basic_ostream<CharT, Traits>&>(), fmt.c_str(), std::declval<local_time<Duration>>(), &abbrev, &offset_sec),
std::basic_string<CharT, Traits, Alloc>{})
{
std::basic_ostringstream<CharT, Traits, Alloc> os;
os.exceptions(std::ios::failbit | std::ios::badbit);
local_time<Duration> _lt(tp.time_since_epoch());
to_stream(os, fmt.c_str(), _lt, &abbrev, &offset_sec);
return os.str();
}
inline bool
parse_by_get_time(const std::string& input, const std::string &format, std::tm & _tm)
{
// Create a stream which we will use to parse the string,
// which we provide to constructor of stream to fill the buffer.
std::istringstream ss{ input };
// Create a tm object to store the parsed date and time.
_tm = { 0,0,0,1,0,70,0,0,0 };
// Now we read from buffer using get_time manipulator
// and formatting the input appropriately.
//ss.imbue(std::locale("en_GB.utf-8"));
ss >> std::get_time(&_tm, format.c_str());
// Convert the tm structure to time_t value and return.
return !ss.fail();
}
// Converts IS8601 time string to a date::time_mills value.
inline bool parse_by_date(const std::string& input, const std::string &format, date::time_mills& mills, int offset = 0)
{
std::istringstream in(input);
std::chrono::minutes offmin(offset);
std::string abovabbrev;
in >> date::parse(format, mills, abovabbrev, offmin);
return !in.fail();
}
//************************************
// 返回当前时区偏移(分钟)
// @return int
//************************************
inline int timezone_offset()
{
static int offset = INT32_MAX;
if (INT32_MAX == offset)
{
time_t _rt = time(NULL);
tm _gtm = *gmtime(&_rt);
tm _ltm = *localtime(&_rt);
time_t _gt = mktime(&_gtm);
tm _gtm2 = *localtime(&_gt);
offset = (int)(((_rt - _gt) + (_gtm2.tm_isdst ? 3600 : 0)) / 60);
}
return offset;
}
//************************************
// Converts time string to a std::tm value.
// Supported format:
// "%Y-%m-%dT%H:%M:%S"
// "%Y-%m-%d"
// "%H:%M:%S"
// @param const std::string & input
// @param std::tm & _tm [out]
// @return bool true if parsed.otherwise false.
//************************************
inline bool parset_datetime(const std::string& input, std::tm& _tm)
{
// Let's consider we are getting all the input in
// this format: '2014-07-25T20:17:22Z' (T denotes
// start of Time part, Z denotes UTC zone).
// A better approach would be to pass in the format as well.
static const std::string dateTimeFormat{ "%Y-%m-%dT%H:%M:%S" };
static const std::string dateFormat{ "%Y-%m-%d" };
static const std::string timeFormat{ "%H:%M:%S" };
static const std::vector<std::string> fmts{ dateTimeFormat, dateFormat, timeFormat };
_tm = { 0,0,0,1,0,70,0,0,0 };
static const std::string p_dateTimeFormat("\\d{2,4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}");
static const std::string p_dateFormat("\\d{2,4}-\\d{1,2}-\\d{1,2}");
static const std::string p_timeFormat("\\d{1,2}:\\d{1,2}:\\d{1,2}");
if (std::regex_match(input, std::regex(p_dateTimeFormat)))
{
if (parse_by_get_time(input, dateTimeFormat, _tm)) {
return true;
}
}
if (std::regex_match(input, std::regex(p_dateFormat)))
{
if (parse_by_get_time(input, dateFormat, _tm)) {
return true;
}
}
if (std::regex_match(input, std::regex(p_timeFormat)))
{
if (parse_by_get_time(input, timeFormat, _tm)) {
return true;
}
}
return false;
}
//************************************
// Converts time string to a time_t value.
// "%Y-%m-%dT%H:%M:%S"
// "%Y-%m-%d"
// "%H:%M:%S"
// @param const std::string & input
// @param time_t & _t
// @return bool true if parsed.otherwise false.
//************************************
inline bool parset_datetime(const std::string& input, time_t& _t)
{
std::tm _tm;
if (parset_datetime(input, _tm))
{
_t = std::mktime(&_tm);
return true;
}
return false;
}
//************************************
// Converts time string to a date::time_mills value.
// "%Y-%m-%dT%H:%M:%S"
// "%Y-%m-%d"
// "%H:%M:%S"
// @param const std::string & input
// @param time_mills & mills
// @return bool true if parsed.otherwise false.
//************************************
inline bool parset_datetime(const std::string& input, date::time_mills& mills)
{
time_t _t;
if (parset_datetime(input, _t))
{
auto _sys_clock = std::chrono::system_clock::from_time_t(_t);
mills = std::chrono::time_point_cast<std::chrono::milliseconds>(_sys_clock);
return true;
}
return false;
}
// Converts time string to a date::time_mills value.
//************************************
// Converts time string to a date::time_mills value.
// "%Y-%m-%dT%H:%M:%S"
// "%Y-%m-%d"
// "%H:%M:%S"
// @param const std::string & input
// @return date::time_mills
//************************************
inline date::time_mills parset_datetime(const std::string& input)
{
date::time_mills mills;
parset_datetime(input, mills);
return mills;
}
//************************************
// Converts IS8601 time string to a date::time_mills value.
// Support fomat:
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param time_mills & mills
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_iso8601(const std::string& input, date::time_mills& mills)
{
const static std::string p1{ "%FT%TZ" };
const static std::string p2{ "%FT%T%Ez" };
const static std::string p3{ "%FT%T%z" };
const static std::string p4{ "%FT%T%Z" };
const static std::string p5{ "%FT%T" };
static const std::vector<std::string> fmts{ p1, p2, p3,p4, p5 };
for (auto fmt : fmts)
{
/** 没有时区的格式使用当前时区 */
int offset = p5 == fmt ? timezone_offset() : 0;
if (parse_by_date(input, fmt, mills, offset))
{
return true;
}
}
return false;
}
//************************************
// Converts IS8601 time string to a std::time_t value.
// Support fomat:
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param std::time_t & _time
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_iso8601(const std::string& input, std::time_t& _time)
{
date::time_mills mills;
if (parse_iso8601(input, mills))
{
_time = (std::time_t)mills.time_since_epoch().count() / 1000;
return true;
}
return false;
}
//************************************
// Converts IS8601 time string to a std::tm value.
// Support fomat:
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param time_mills & mills
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_iso8601(const std::string& input, std::tm& _tm)
{
date::time_mills mills;
if (parse_iso8601(input, mills))
{
std::time_t _time = (std::time_t)mills.time_since_epoch().count() / 1000;
std::tm *__tm = std::localtime(&_time);
_tm = *__tm;
return true;
}
return false;
}
//************************************
// Converts IS8601 time string to a date::time_mills value.
// Support fomat:
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @return date::time_mills
//************************************
inline date::time_mills parse_iso8601(const std::string& input)
{
date::time_mills mills;
parse_iso8601(input, mills);
return mills;
}
//************************************
// Converts time string to a date::time_mills value.
// Support fomat:
// %Y-%m-%dT%H:%M:%S
// %Y-%m-%d
// %H:%M:%S
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param time_mills & mills
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_uni_datetime(const std::string& input, date::time_mills& mills)
{
if (parset_datetime(input, mills))
{
return true;
}
if (parse_iso8601(input, mills))
{
return true;
}
return false;
}
//************************************
// Converts time string to a std::time_t value.
// Support fomat:
// %Y-%m-%dT%H:%M:%S
// %Y-%m-%d
// %H:%M:%S
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param std::time_t & _time
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_uni_datetime(const std::string& input, std::time_t& _time)
{
date::time_mills mills;
if (parse_uni_datetime(input, mills))
{
_time = (std::time_t)(mills.time_since_epoch().count() / 1000);
return true;
}
return false;
}
//************************************
// Converts time string to a std::tm value.
// Support fomat:
// %Y-%m-%dT%H:%M:%S
// %Y-%m-%d
// %H:%M:%S
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @param std::tm & _tm
// @return bool true if parsed.otherwise false.
//************************************
inline bool parse_uni_datetime(const std::string& input, std::tm& _tm)
{
if (parset_datetime(input, _tm))
{
return true;
}
return parse_iso8601(input, _tm);
}
//************************************
// Converts IS8601 time string to a date::time_mills value.
// Support fomat:
// %Y-%m-%dT%H:%M:%S
// %Y-%m-%d
// %H:%M:%S
// %FT%TZ
// %FT%%Z
// %FT%T%Ez
// @param const std::string & input
// @return date::time_mills
//************************************
inline date::time_mills parse_uni_datetime(const std::string& input)
{
date::time_mills mills;
parse_uni_datetime(input, mills);
return mills;
}
//************************************
// 系统时间(毫秒)转为本地时间(毫秒)
// @param const time_mills & _sys_time
// @return date::time_mills
//************************************
inline time_mills to_local_time(const date::time_mills&_sys_time)
{
return time_mills(std::chrono::milliseconds(_sys_time.time_since_epoch().count() + timezone_offset() * 60 * 1000));
}
//************************************
// 本地时间(毫秒)转为系统时间(毫秒)
// @param const time_mills & _loc_time
// @return date::time_mills
//************************************
inline time_mills to_system_time(const date::time_mills&_loc_time)
{
return time_mills(std::chrono::milliseconds(_loc_time.time_since_epoch().count() - timezone_offset() * 60 * 1000));
}
//************************************
// 根据fmt指定的格式将系统时间格式化为字符串
// @param const std::string & fmt
// @param const time_mills & tp
// @param const std::string & abbrev 时区缩写
// @param const std::chrono::seconds & offset_sec 时区偏移(秒)
// @return std::string
//************************************
inline std::string format(const std::string& fmt, const time_mills& tp, const std::string& abbrev = { "UTC" }, const std::chrono::seconds& offset_sec = std::chrono::seconds(0))
{
return date::format<>(fmt, to_local_time(tp), abbrev, offset_sec);
}
//************************************
// 系统时间格式化为ISO8601格式字符串
// @param const time_mills & tp
// @return std::string
//************************************
inline std::string format_iso8601(const time_mills& tp)
{
return format("%FT%T%z", tp, "", std::chrono::seconds(timezone_offset() * 60));
}
//************************************
// 系统时间格式化为ISO8601格式字符串
// @param time_t _time
// @return std::string
//************************************
inline std::string format_iso8601(time_t _time)
{
date::time_mills mills(std::chrono::seconds((int64_t)_time));
return format_iso8601(mills);
}
//************************************
// 系统时间(毫秒)格式化为ISO8601格式字符串
// @param int64_t _time
// @return std::string
//************************************
inline std::string format_iso8601_mills(int64_t _time)
{
date::time_mills mills(std::chrono::milliseconds((int64_t)_time));
return format_iso8601(mills);
}
//************************************
// 系统时间格式化为ISO8601格式字符串
// @param const std::tm & _tm
// @return std::string
//************************************
inline std::string format_iso8601(const std::tm & _tm)
{
std::time_t _time = std::mktime((std::tm*)&_tm);
return format_iso8601(_time);
}
} /** namespace date */
namespace std {
//************************************
// 重载操作符,将系统时间输出到ostream
// @param ostream & os
// @param const date::time_mills & tp
// @return std::ostream&
//************************************
inline std::ostream& operator<<(std::ostream& os, const date::time_mills& tp)
{
return date::operator<<(os, tp);
}
}/** namespace std */
#endif /* COMMON_SOURCE_CPP_DATE_UTILITS_H_ */
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/l0km/common_source_cpp.git
git@gitee.com:l0km/common_source_cpp.git
l0km
common_source_cpp
common_source_cpp
master

搜索帮助

D67c1975 1850385 1daf7b77 1850385