boost local_date_time 数学错误?

发布于 2024-08-20 17:13:23 字数 1509 浏览 6 评论 0原文

我在我的项目中使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独自唱情﹋歌 2024-08-27 17:13:23

我认为问题在于提问者对一天是什么的概念。他希望这里是“约会”日,而不是 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?

夜巴黎 2024-08-27 17:13:23

您应该创建一个 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 !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文