将unix时间戳(s)转换为c++中的星期几
Convert unix timestamp (s) to day of week in C++?
如何根据任意Unix时间戳(秒)确定加利福尼亚的星期几(太平洋时间)?我搜索了一下,但是没有找到c++的内置库。
UTC通常比PT早8小时,但简单地从Unix时间戳中减去8小时并创建tm
结构体不起作用,因为这会忽略夏令时的细微差别。
下面是如何使用Howard Hinnant的日期库。这是一个免费的麻省理工学院许可的c++ 11/14库,基于<chrono>
:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace std::chrono_literals;
using namespace date;
auto unix_timestamp = sys_seconds{1479664467s};
auto zt = make_zoned("America/Los_Angeles", unix_timestamp);
auto wd = weekday{floor<days>(zt.get_local_time())};
std::cout << wd << 'n';
}
第一行只是构造unix时间戳(您可能从其他来源获得)。在c++ 11中,我们没有时间字面值,所以这一行应该是:
auto unix_timestamp = sys_seconds{seconds{1479664467}};
make_zoned()
基于unix_timestamp
和time_zone
"America/Los_Angeles"创建zoned_time<seconds>
。zoned_time
是time_zone
和unix时间戳的集合。
您可以使用zt.get_local_time()
从zoned_time
中获得本地时间。这是一个chrono::time_point
,但没有时钟与它相关联。此时间点的精度将等于原始时间戳的精度(在本例中为秒)。
您可以通过截断local_time
到days
的精度来获得local_time
的本地星期几:
floor<days>(zt.get_local_time())
日期精度time_point
将转换为类型weekday
。
weekday
可以打印出来,也可以参与weekday
的运算和比较,也可以显式转换为[0,6]范围内的unsigned
。
上面的程序输出:
Sun
这个库的时区部分是IANA时区数据库的忠实表示。它将给出本地时区和UTC之间的正确调整,时间可以追溯到19世纪中期到现在。如果您传递的库时间戳早于19世纪中期,则已知最早的UTC偏移量将向后推断至-32768年。您还可以将时间戳传递到遥远的32767年,并且当前的偏移量和夏令时规则将向前传播。
因为这个库是建立在<chrono>
之上的,所以它可以处理<chrono>
提供的任何精度。请注意,一些chrono::duration
s,如nanoseconds
,具有更有限的范围(nanoseconds
的+/-292年)。
库/进程是线程安全的。也就是说,该程序直接使用您指定的任何时区,而无需更改计算机的时区或环境变量。它也不涉及C计时API的一部分,由于非const函数的局部静态,这部分已知不是线程安全的。
已移植到最新版本的gcc、clang和VS.
更新c++ 20
上面的程序可以很容易地移植到c++ 20(在我写这篇文章的时候,有些供应商支持这个,有些还不支持):
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
auto unix_timestamp = sys_seconds{1479664467s};
auto zt = zoned_time{"America/Los_Angeles", unix_timestamp};
auto wd = weekday{floor<days>(zt.get_local_time())};
std::cout << wd << 'n';
}
使用标准UNIX C(非线程安全版本)的hack方法:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void print_times() {
char my_buf[100];
time_t now = time(NULL);
printf(ctime(&now));
strftime(my_buf, 100, "DoW=%w Tz=%Zn", localtime(&now));
printf(my_buf);
}
int main( int argc, char * argv[] ) {
print_times();
setenv("TZ", "America/Los_Angeles", 1);
print_times();
unsetenv("TZ");
print_times();
}
不幸的是,TZ
env var或更改文件/etc/localtime
是影响UNIX时间函数的时区设置的唯一方法(在底层,tzset()使用这些源来初始化一组共享变量,这些变量对所有库函数的时区设置进行编码)。
问题是您需要为您需要的区域提供UNIX TZ字符串。Zoneinfo格式是最简单且推荐使用的格式。我使用tzselect
来生成太平洋时间的TZ值。
关于标准UNIX时区设置的信息,请参见man 5 localtime
, man tzselect
。
可以使用Boost库吗?如果您可以为您的时区(PST)找出Posix时区字符串(IEEE Std 1003.1,请参阅http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zone),那么下面的示例可能会有所帮助。
#include <iostream>
#include <ctime>
#include <boost/date_time.hpp>
int main(int argc, char ** argv)
{
std::string posix_time_zone_string = "EST-05:00:00"; // you need to change this to the posix time representation of your desired timezone
time_t unix_time = 1479641855; //1479641855 = Sun, 20 Nov 2016 11:37:35 GMT
boost::posix_time::ptime pt = boost::posix_time::from_time_t(unix_time);
std::cout << "time in UTC: " << boost::posix_time::to_iso_extended_string(pt) << std::endl;
boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone(posix_time_zone_string));
boost::local_time::local_date_time dt_with_zone(pt, zone);
std::cout << "time in local timezone: " << boost::posix_time::to_iso_extended_string(dt_with_zone.local_time()) << std::endl;
// Get the week day (alternative 1)
std::cout << "local week day integer: " << boost::local_time::to_tm(dt_with_zone).tm_wday << std::endl; // 0=sunday, 1=monday, etc.
// Get the week day (alternative 2)
std::cout << "local week day name: " << dt_with_zone.local_time().date().day_of_week() << std::endl;
std::cout << "local week day integer: " << int(dt_with_zone.local_time().date().day_of_week()) << std::endl;
return 0;
}
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++