简体   繁体   English

在MSVC中获取DST以获取否定的“ time_t”

[英]Getting DST for negative `time_t` in MSVC

I am trying to determine whether a given time_t value is in DST for the given timezone. 我试图确定给定时区的DST中是否有给定的time_t值。 So I wrote something like the following: 所以我写了类似下面的东西:

inline bool is_DST(time_t t) {
    struct tm* ti = localtime(&t);
    return ti->tm_isdst > 0;
}

This works great for current-ish times. 这对于当前的时代很有用。 For example, on a current time_t value it returns true . 例如,在当前的time_t值上,它返回true For the J2000 epoch, it returns false . 对于J2000时期,它返回false Nice. 尼斯。

Unfortunately, the MSVC variant of localtime(...) returns nullptr on negative input. 不幸的是, localtime(...)的MSVC变体在负输入上返回nullptr Reading the docs linked above tells me it also will fail after year 3000. So, for example (time_t)(-1) (corresponding to 1969-12-31 23:59:59) will cause a segfault. 阅读上面链接的文档会告诉我,它也将在3000年后失败。因此,例如(time_t)(-1) (对应于1969-12-31 23:59:59)将导致段错误。

This is bad. 这不好。 1969 wasn't that long ago. 1969年不久。 Standard practice is to extrapolate UTC with the assumption that there are no leap seconds either before 1972 or anywhere in the future (until announced). 标准做法是假设1972年之前或将来的任何地方都没有leap秒来推断UTC(直到宣布)。 * *

What are my options to implement is_DST(...) that will work for the range of dates given by a 64-bit time_t (±2.9*10 11 years or so) based on above extrapolation? 根据上述推论,实现is_DST(...)适用于64位time_t给定的日期范围(±2.9 * 10 11年左右)时,我有哪些选择?

* There's some question as to whether this is the right thing. * 关于这是否正确,存在一些疑问。 Leap seconds were introduced in 1972, and extrapolating UTC backward means you have to assume there weren't leap seconds (there would have been). seconds秒是在1972年引入的,向后外推UTC意味着您必须假设没有leap秒(应该是)。 And extrapolating UTC forward is hard too, because Earth's rotation makes leap seconds unpredictable. 而且,将UTC向前推算也很困难,因为地球的自转使seconds秒变得不可预测。

Here is the library ildjarn refers to in the comments: 这是ildjarn在评论中引用的库:

https://github.com/HowardHinnant/date https://github.com/HowardHinnant/date

It is open source and works on VS-2013 and later. 它是开源的,适用于VS-2013及更高版本。 Here is how you would use it to implement is_DST : 这是使用它来实现is_DST

#include "tz.h"
#include <ctime>

bool
is_DST(std::time_t t)
{
    using namespace std::chrono;
    using namespace date;
    return current_zone()->get_info(system_clock::from_time_t(t)).save != 0min;
}

This will work for negative time_t , but not for the full range of a 64bit time_t (which would be +/- 292 billion years). 这将对负time_t ,但不适用于64位time_t的整个范围(这将是+/- 2,920亿年)。 But it will easily go back to the mid 1800's when uniform time was first introduced. 但是它很容易回到最初引入统一时间的1800年代中期。

On Windows you will either have to install libcurl , or manually download the IANA timezone database . 在Windows上,您将必须安装libcurl或手动下载IANA时区数据库

If you would like to answer this question for some time zone other than the computer's current one, that is easy enough: 如果您想在除计算机当前时间段以外的某个时区回答此问题,那很容易:

return locate_zone("Europe/Monaco")
                        ->get_info(system_clock::from_time_t(t)).save != 0min;

The range on Windows is [-27258-04-19 21:11:54.5224192, 31197-09-14 02:48:05.4775807] . Windows上的范围是[-27258-04-19 21:11:54.5224192, 31197-09-14 02:48:05.4775807] The restriction on this range is that this is the range of the VS system_clock::time_point (which has a precision of 100ns, and is stored as a int64_t ). 此范围的限制是,这是VS system_clock::time_point的范围(精度为100ns,并存储为int64_t )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM