/** ================================* eli960@qq.com* http://linuxmail.cn/* 2024年02月18日* ================================*/#include "zcc/zcc_stdlib.h"#include <mutex>#include <unordered_map>#include <chrono>#include <ctime>#include <fstream>#include <vector>#include <cstring>#include <time.h>#ifdef _WIN64#include <timezoneapi.h>#else // _WIN64#include <poll.h>#include <limits.h>#include <unistd.h>#endif // _WIN64zcc_namespace_begin;/*** @brief 根据传入的星期几的数字返回对应的缩写字符串** @param day 星期几的数字,范围0-6,0表示周日,6表示周六* @return const char* 对应的星期缩写字符串*/const char *get_day_abbr_of_week(int day){// 定义星期缩写数组static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};// %w// 如果传入的数字小于0,将其置为0if (day < 0){day = 0;}// 如果传入的数字大于6,将其置为6if (day > 6){day = 6;}return days[day];}const char *get_day_name_of_week(int day){// 定义星期缩写数组static const char *days[] = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};// %w// 如果传入的数字小于0,将其置为0if (day < 0){day = 0;}// 如果传入的数字大于6,将其置为6if (day > 6){day = 6;}return days[day];}/*** @brief 根据传入的月份数字返回对应的缩写字符串** @param month 月份数字,范围0-11,0表示一月,11表示十二月* @return const char* 对应的月份缩写字符串*/const char *get_month_abbr(int month){// 定义月份缩写数组static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};// %m - 1// 如果传入的数字小于0,将其置为0if (month < 0){month = 0;}// 如果传入的数字大于11,将其置为11if (month > 11){month = 11;}return months[month];}const char *get_month_name(int month){// 定义月份名称数组static const char *months[] = {"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"};// %m - 1// 如果传入的数字小于0,将其置为0if (month < 0){month = 0;}// 如果传入的数字大于11,将其置为11if (month > 11){month = 11;}return months[month];}int get_weekday_between(int day1 /* 0 - 6 */, int day2){int diff = abs(day2 - day1);return diff < 7 - diff ? diff : 7 - diff;}/*** @brief 获取当前时间的秒和微秒部分** @return timeofday 包含秒和微秒的结构体*/timeofday gettimeofday(){timeofday r;// 获取当前系统时间auto now = std::chrono::system_clock::now();// 获取从纪元开始到现在的持续时间auto duration_since_epoch = now.time_since_epoch();// 将持续时间转换为微秒auto millis = std::chrono::duration_cast<std::chrono::microseconds>(duration_since_epoch).count();r.tv_sec = millis / (1000 * 1000);r.tv_usec = millis % (1000 * 1000);return r;}int64_t millisecond(){return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();}int64_t microsecond(){return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();}/*** @brief 让当前线程休眠指定的毫秒数** @param delay 休眠时间(毫秒)*/void sleep_millisecond(int64_t delay){#ifdef _WIN64// 在Windows 64位系统下,使用标准库的sleep_for函数进行休眠std::this_thread::sleep_for(std::chrono::milliseconds(delay));#else // _WIN64int64_t left = delay;// 计算休眠结束的时间戳int64_t end = millisecond() + left + 1;while (left > 0){// 使用poll函数进行等待poll(0, 0, (int)left);// 计算剩余的休眠时间left = end - millisecond();}#endif // _WIN64}/*** @brief 计算从当前时间到指定时间戳的剩余毫秒数** @param stamp 指定的时间戳(毫秒)* @return int64_t 从当前时间到指定时间戳的剩余毫秒数*/int64_t millisecond_to(int64_t stamp){return stamp - millisecond();}/*** @brief 获取当前时间的秒级时间戳** @return int64_t 当前时间的秒级时间戳*/int64_t second(void){// 获取当前系统时间auto const clock_now = std::chrono::system_clock::now();// 将系统时间转换为C标准时间std::time_t time = std::chrono::system_clock::to_time_t(clock_now);return time;}/*** @brief 让当前线程休眠指定的秒数** @param delay 休眠时间(秒)*/void sleep(int64_t delay){// 调用sleep_millisecond函数,将秒数转换为毫秒数sleep_millisecond(delay * 1000);}/*** @brief 根据指定的时间戳生成符合RFC 7231标准的时间字符串** @param t 时间戳* @return std::string 符合RFC 7231标准的时间字符串*/std::string rfc7231_time(int64_t t){char buf[128 + 1];if (t == var_use_current_time){t = second();}// 将时间戳转换为UTC时间结构体std::tm *now_tm = gmtime(t);// 格式化时间字符串std::strftime(buf, 128, "%a, %d %b %Y %H:%M:%S GMT", now_tm);return buf;}/*** @brief 根据指定的时间戳生成符合RFC 822标准的时间字符串** @param t 时间戳,如果小于1则使用当前时间* @return std::string 符合RFC 822标准的时间字符串*/std::string rfc822_time(int64_t t){std::string r;char buf[128 + 1];if (t == var_use_current_time){t = second();}// 将时间戳转换为本地时间结构体auto p = localtime(t);// FIXME %Z// std::strftime(buf, 128, "%a, %d %b %Y %H:%M:%S %z", p);// 添加星期缩写r.append(get_day_abbr_of_week(p->tm_wday));// 添加月份和日期std::strftime(buf, 128, ", %d ", p);r.append(buf);// 添加月份缩写r.append(get_month_abbr(p->tm_mon));// 添加剩余部分std::strftime(buf, 128, " %Y %H:%M:%S %z", p);r.append(buf);return r;}std::string get_hh_mm(int64_t t){if (t == var_use_current_time){t = second();}auto p = localtime(t);char buf[128 + 1];std::sprintf(buf, "%02d:%02d", p->tm_hour, p->tm_min);return buf;}int get_yyyyymmdd(int64_t t){if (t == var_use_current_time){t = second();}auto p = localtime(t);return (p->tm_year + 1900) * 10000 + (p->tm_mon + 1) * 100 + p->tm_mday;}ZCC_LIB_API std::string get_simple_date(int64_t t){if (t == var_use_current_time){t = second();}char buf[128 + 1];auto p = localtime(t);std::strftime(buf, 128, "%Y-%m-%d", p);return buf;}/*** @brief 将时间戳转换为简单的日期时间字符串** @param t 时间戳,如果小于1则使用当前时间* @return std::string 格式为" %Y %H:%M:"的日期时间字符串*/std::string simple_date_time(int64_t t){char buf[128 + 1];if (t == var_use_current_time){t = second();}auto p = localtime(t);std::strftime(buf, 128, "%Y-%m-%d %H:%M", p);return buf;}std::string simple_date_time_with_second(int64_t t){char buf[128 + 1];if (t == var_use_current_time){t = second();}auto p = localtime(t);std::strftime(buf, 128, "%Y-%m-%d %H:%M:%S", p);return buf;}int64_t day_to_unix(int year, int month, int mday, const std::string &tzid){std::string use_tzid = tzid.empty() ? get_current_timezone() : tzid;if (use_tzid.empty()){use_tzid = "UTC";}std::tm base_tm = {};base_tm.tm_year = year - 1900;base_tm.tm_mon = month - 1;base_tm.tm_mday = mday;base_tm.tm_hour = 0;base_tm.tm_min = 0;base_tm.tm_sec = 0;base_tm.tm_isdst = -1;int64_t unix_scond = zcc::timegm(&base_tm);timezone_info tzinfo = get_timezone_info(use_tzid, unix_scond);unix_scond -= tzinfo.gmtoff;return unix_scond;}int64_t day_to_unix(int64_t yyyymmdd, const std::string &tzid){int year = yyyymmdd / 10000;int month = (yyyymmdd / 100) % 100;int mday = yyyymmdd % 100;if (year <= 1900 || year >= 2100){return var_invalid_time;}if (month < 1 || month > 12){return var_invalid_time;}if (mday < 1 || mday > 31){return var_invalid_time;}return day_to_unix(year, month, mday, tzid);}/*** @brief 将tm结构体转换为UTC时间戳** @param tm 指向tm结构体的指针* @return int64_t UTC时间戳*/int64_t timegm(struct tm *tm){#ifdef _WIN64// 在Windows 64位系统下,使用mktime函数转换时间int64_t t = (int64_t)::mktime(tm);TIME_ZONE_INFORMATION tzi;// 获取时区信息GetTimeZoneInformation(&tzi);// 减去时区偏移量t -= tzi.Bias * 60;return t;#else // _WIN64// 在非Windows系统下,使用系统的timegm函数return ::timegm(tm);#endif // _WIN64}int64_t timelocal(struct tm *tm){#ifdef _WIN64// 在Windows 64位系统下,使用mktime函数转换时间return (int64_t)::mktime(tm);#else // _WIN64// 在非Windows系统下,使用系统的timegm函数return ::timelocal(tm);#endif // _WIN64}thread_local struct tm gmtime_static_buf;struct tm *localtime(const int64_t unix_second){#ifdef _WIN64localtime_s(&gmtime_static_buf, (time_t *)&unix_second);return &gmtime_static_buf;#elsereturn ::localtime_r((time_t *)&unix_second, &gmtime_static_buf);#endif}struct tm *gmtime(const int64_t unix_second){#ifdef _WIN64::gmtime_s(&gmtime_buf, (time_t *)&unix_second);return &gmtime_buf;#elsereturn ::gmtime_r((time_t *)&unix_second, &gmtime_static_buf);#endif}zcc_namespace_end;
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型