如何根据任意Unix时间戳(秒)来确定加利福尼亚州(太平洋时间)一周中的哪一天?我已经搜索过,但还没有找到C++的内置库。将C++中的unix时间戳转换为星期几?
UTC通常比PT早8小时,但是从Unix时间戳简单地减去8小时并创建tm
结构不起作用,因为这会折扣日光节约细微差别。
如何根据任意Unix时间戳(秒)来确定加利福尼亚州(太平洋时间)一周中的哪一天?我已经搜索过,但还没有找到C++的内置库。将C++中的unix时间戳转换为星期几?
UTC通常比PT早8小时,但是从Unix时间戳简单地减去8小时并创建tm
结构不起作用,因为这会折扣日光节约细微差别。
以下是使用Howard Hinnant's date library的方法。这是一种基于<chrono>
自由MIT许可C++十四分之十一库:
#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
“美国/洛杉矶”一zoned_time<seconds>
。 A 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
。
A weekday
可以打印出来,参与weekday
算术和比较,或明确转换为范围[0,6]范围内的unsigned
。
上述程序输出:
Sun
这个库的时区部分是IANA timezone database的忠实代表。它将在本地时区和UTC之间进行正确的调整,早在1800年代中期到现在。如果您在1800年代中期之前通过了图书馆时间戳,则最早的已知UTC时间戳会推迟到年份-32768。您还可以在未来将时间戳作为32767年的时间传递,并且当前偏移量和夏令时规则将向前传播。
由于该库基于<chrono>
构建,因此它将处理<chrono>
提供的任何精度。请注意,某些chrono::duration
(如nanoseconds
)的范围更有限(nanoseconds
为+/- 292年)。
库/进程是线程安全的。也就是说,该程序可直接与您指定的任何时区一起工作,而无需更改计算机的时区或环境变量。它也不涉及C时序API的部分,由于非const函数本地静态,已知它们不是线程安全的。
移植到最新版本的gcc,clang和VS.
你可以使用Boost库吗? 如果您可以找出时区(PST)的Posix时区字符串(IEEE标准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;
}
使用标准的UNIX C(非线程安全版本)哈克的方式:
#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=%Z\n", 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
的环境变量或更改文件/etc/localtime
是唯一的方法可以实现为UNIX时间功能的时区设置(在引擎盖tzset()使用这些源来初始化一组共享变量,这些变量对所有库函数的时区设置进行编码)。
一个问题是,您需要为UNIX(TZ)字符串提供所需的区域。格式是最简单并且推荐使用的格式。我用tzselect
为太平洋时间生成TZ值。
有关标准UNIX时区设置的信息,另请参阅man 5 localtime
,man tzselect
。
我没有downvote你,但如何['std :: localtime'](http://en.cppreference.com/w/cpp/chrono/c/localtime)? – Danh
谢谢 - 如果当地时间对我来说不是PT呢? –
[strftime](http://en.cppreference.com/w/cpp/chrono/c/strftime)。或[time_put](http://en.cppreference.com/w/cpp/locale/time_put)。或[霍华德Hinnant的日期](https://github.com/HowardHinnant/date) - 指针,而不是答案,这是为什么评论。 –