【问题标题】:Getting offset by 1 day when converting NTP time to date将 NTP 时间转换为日期时偏移 1 天
【发布时间】:2023-04-02 08:09:02
【问题描述】:

我正在尝试实现自己的 NTP 客户端。

我可以发送和接收 NTP 消息,我现在需要做的就是将其转换为“实时”时间。我创建了一个函数来执行此操作,但由于某种原因,我得到了正确的所有字段,除了晚 1 天的 day 字段。

我还使用笔、纸和计算器进行了一些快速计算,得到了相同的结果,所以一定有一些我遗漏的东西。

这是我的代码:

void setTime(uint32_t seconds, uint32_t fraction)
{
    int yearsPassed = seconds / (60 * 60 * 24 * 365);

    year = 1900 + yearsPassed;

    int leapYears = yearsPassed / 4;

    int secondsLeft = seconds - yearsPassed * 365 * 24 * 60 * 60;

    secondsLeft -= leapYears * 60 * 60 * 24;

    int daysPassed = secondsLeft / (60 * 60 * 24);

    secondsLeft -= daysPassed * 60 * 60 * 24;

    int hoursPassed = secondsLeft / (60*60);

    secondsLeft -= hoursPassed * 60 * 60;

    int minutesPassed = secondsLeft / 60;

    secondsLeft -= minutesPassed * 60;

    hour = hoursPassed + SUMMERTIME_OFFSET;
    minute = minutesPassed;
    second = secondsLeft;

    us = (fraction * (pow((float)10,(float)6)) / (pow((float)2,(float)32)));

    month = getMonth(daysPassed);
    day = getDay(month, daysPassed);
}

例如,使用此代码,我可以获取时间 2015/4/28 14:3:15.351731,但日期应该是 29 而不是 28。我最初的想法是我计算的闰年有误,因此错过了 1 天那个,但这似乎是正确的。

编辑

getMonth() 和 getDay() 的代码。它们还没有完全实现,因为我想编写尽可能少的代码来测试它是否有效。

int getMonth(int daysPassed)
{
    if (daysPassed < 32)
        return 1;
    else if (daysPassed < 60)
        return 2;
    else if (daysPassed < 91)
        return 3;
    else if (daysPassed < 121)
        return 4;
    else if (daysPassed < 152)
        return 5;
    else 
        return 6;
}

int getDay(int month, int daysPassed)
{
    switch (month)
    {
    case 1:
        return daysPassed;
        break;
    case 2:
        return daysPassed - 31;
        break;
    case 3:
        return daysPassed - 59;
        break;
    case 4:
        return daysPassed - 90;
        break;
    case 5:
        return daysPassed - 120;
        break;
    default:
        return 6;
        break;
    }
}

【问题讨论】:

  • 您能打印那里所有变量的值并将其添加到问题中吗?这将节省人们大量计算或重新实现代码的时间。很有可能,您在执行此操作时会自己发现问题。
  • 你的getDay(...)getMonth(...) 是什么样子的(另外,他们为什么不需要知道他们是否在闰年?
  • ...它们在 1900 年 1 月 1 日是如何工作的?
  • @Roland Shaw 我在尝试让它工作时忽略了当前日期的闰年方面,因为今年不是闰年
  • @AlexNevidomsky 他们如何在 1900 年 1 月 1 日工作?你的意思是如果我将 0 传递给 setTime() 函数?它显示 1900/01/00。这是否意味着您总是必须多加一天?

标签: c++ math time ntp


【解决方案1】:

您的daysPast 出现了围栏错误,因为它是已完成 天,而不是部分 天数。

考虑 1 秒的输入(哎呀,更好的是,让它成为一个单元测试),它应该解析为 1/1/1900 00:00:01 - 它会将您的 daysPast 设为 0,而这是过去的天数,不考虑当天。

当然,在计算年份中的日期时,您还需要考虑当前年份是否为闰年;为了完整性和 2100 年的兼容性,您的闰年过去算法有点幼稚。

【讨论】:

  • 好的,所以我总是需要多加 1 天?而且我完全知道我获取当前日期/月份的函数不考虑闰年,我只是想在继续之前用尽可能少的代码对其进行测试。 2100 年有什么特别之处?
  • 2100 年不是闰年(就像 1900 年不是),尽管它可以被 4 整除,因为它可以被 100 整除,而不是被 400 整除。是的,您需要通过调整getDay 的结果和调整getMonth 中的偏移量来修复您的fencepost 错误
猜你喜欢
  • 2018-02-20
  • 1970-01-01
  • 2019-10-10
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多