boost local_date_time 数学错误?
我在我的项目中使用 Boost 的日期时间库。当我发现它具有小时、天、月、年等持续时间类型时,我非常高兴,并且它们根据您添加的内容更改其值(即添加 1 个月,将日期的月份部分提前) ,它不只是增加 30 天或类似的时间)。我认为此属性适用于 days 类型,但我决定在将其投入生产之前对其进行测试...
local_date_time t1(date(2010, 3, 14), hours(1), easternTime, false); // 1am on DST transition date
{
CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year());
CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month());
CPPUNIT_ASSERT_EQUAL(greg_day(14), t1.local_time().date().day());
CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds());
}
t1 += days(1); // the time in EST should now be 1am on the 15th
{
CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year());
CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month());
CPPUNIT_ASSERT_EQUAL(greg_day(15), t1.local_time().date().day());
CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours()); // fails, returns 2
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds());
}
在上面您将看到我的 CPPUNIT 单元测试。它在指示的行处失败,值为 2,这是我所期望的,如果 days() 仅添加 24 小时,而不是 1 个逻辑日(因为 DST 转换导致 2010-03-14 在 EST 中长为 23 小时)。
我做错了什么吗?这是一个错误吗?我是否完全误解了图书馆在这种数学方面的设计目标?
I'm using Boost's datetime library in my project. I was very happy when I discovered that it has time duration types for hours, days, months, years, etc, and they change their value based on what you're adding them to (i.e. adding 1 month advances the month part of the date, it doesn't just add 30 days or somesuch). I thought this property held for the days type, but I decided to test it before I put it into production...
local_date_time t1(date(2010, 3, 14), hours(1), easternTime, false); // 1am on DST transition date
{
CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year());
CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month());
CPPUNIT_ASSERT_EQUAL(greg_day(14), t1.local_time().date().day());
CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds());
}
t1 += days(1); // the time in EST should now be 1am on the 15th
{
CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year());
CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month());
CPPUNIT_ASSERT_EQUAL(greg_day(15), t1.local_time().date().day());
CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours()); // fails, returns 2
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes());
CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds());
}
Above you'll see my CPPUNIT unit test. It fails at the indicated line with 2, which is what I would expect if days() merely added 24 hours, instead of 1 logical day (since the DST transition causes 2010-03-14 to be 23 hours long in EST).
Am I doing something wrong? Is this a bug? Did I just completely misunderstand the design goal of the library with respect to this sort of math?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为问题在于提问者对一天是什么的概念。他希望这里是“约会”日,而不是 24 小时,但这并不是一个合理的要求。
如果在当地时间工作,必然会遇到奇特的效果。例如,如果在将时钟从凌晨 1 点提前到凌晨 2 点的时区中,如果您的本地时间“添加日期”计算应将(不存在的)相关星期日上午的上午 1.30 设置为(不存在),您预计会发生什么情况?
时间计算必须向前推进 24 小时 - 它必须在基础 UTC 时间上运行。
要按照所述进行“跳跃一天”计算,请使用 Boost 的日期类型,并且仅添加一天中的时间作为最终操作。
能够提前一个月的业务是完全不同的,因为与一天不同,日历月作为持续时间没有特定的含义。这也会带来麻烦:如果您从 1 月 31 日起提前一个日历月,然后返回一个日历月,最终会得到什么日期?
I think the problem is in the asker's conception of what a day is. He wants it to be a 'date' day here, rather than 24 hours, but that is not a reasonable thing to ask for.
If working in local time, one is bound to encounter peculiar effects. For example, what do you expect to happen if, in a timezone that puts clocks forward from 1am to 2am, if your local time 'add date day' calculation should set the (non existent) 1.30am on the relevant Sunday morning?
A time calculation has got to move forward 24 hours - it must operate on the underlying UTC time.
To make the 'jump one day' calculation as described, work with Boost's date type, and only add in the time-of-day as the final action.
The business of being able to advance a month is quite different, because, unlike a day, a calendar month has no specific meaning as a duration. And it causes troubles too: if you advance one calendar month from 31st January, and then go back one calendar month, what date do you end up with?
您应该创建一个 boost::posix_time::time_duration 对象并将其添加到您的本地时间,而不是添加 date_duration 对象 days ,如下所示:
boost::posix_time::time_duration td ( 24 , 0 , 0 , 0 ) ; //24小时0分秒纳米
boost::local_time::local_date_time 稍后 = 现在 + td ; //假设现在是你的开始 //local_date_time , 2010-3-14
//later 现在将是一个充分考虑 DST 的本地 date_time 对象!
Instead of adding the date_duration object days , you should create a boost::posix_time::time_duration object and add this to your local time , like so:
boost::posix_time::time_duration td ( 24 , 0 , 0 , 0 ) ; //24 hours, 0 minutes, seconds, nano
boost::local_time::local_date_time later = now + td ; //assuming that now is your starting //local_date_time , 2010-3-14
//later will now be a local date_time object that takes full account of DST !