找到给出年份,月份和C / C ++月份中“第n”日出现的日期

时间:2015-08-19 14:47:29

标签: c++ c datetime timezone dst

为了使设备(内存有限)能够管理自己的时区和夏令时,我正在尝试根据每个时区的简化描述计算85个时区的夏令时触发器。我可以访问设备中的最小C和C ++库。每个时区的时区(包括DST)描述的格式如下:

  • UTC - 系统时钟的基准时间和日期
  • GMTOffsetMinutes - 偏离GMT且DST无效
  • DSTDeltaMinutes - DST有效的修改器(适用于TZ)
  • DSTStartMonth - DST变为活动的月份
  • DSTStartNthOccurranceOfDay - 第n次出现的日期名称
  • DSTDayOfWeek - Sun = 0到Sat = 6
  • DSTStartHour - DST生效的小时
  • DSTStartMinute - DST变为活动的分钟
  • 和相应的EndMonth,EndNth ...,EndHour,EndMinute

我发现很多例子都是另一种方式,即从日期开始,但它们涉及使用模数,保留余数并丢弃商,因此我无法转换公式以满足我的需要。

我还尝试重复使用标准“Jan = 6,Feb = 2,Mar = 2,Apr = 5,May = 0等修改器表和年份修改器”告诉我6月25日哪天, 2067年是“派对技巧,并开发了以下算法。

Date = DayOfWeek + ((NthOccuranceOfDay - 1) x 7 ) - MonthCode - YearCode

这适用于我选择的前6个随机测试日期,但之后我开始查看失败的日期。基本算法是否可能是声音但是我错过了另一个修饰符,或者我错误地应用了修饰符?

我可以使用另一种解决方案吗?

2 个答案:

答案 0 :(得分:1)

使用this open source, cross platform date library,可以写:

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    year_month_day us_daylight_starts = sys_days(sun[2]/mar/2015);
    year_month_day us_daylight_ends   = sys_days(sun[1]/nov/2015);
    std::cout << us_daylight_starts << '\n';
    std::cout << us_daylight_ends << '\n';
}

将输出:

2015-03-08
2015-11-01

此库所基于的公式位于公共领域且documented here

算法论文有非常完整的单元测试,可以在数百万年的范围内验证日期算法(范围远大于必要的范围)。

有时,夏令时规则是根据 last 一个月的工作日编写的。这很容易处理:

year_month_day ymd = sys_days(sun[last]/nov/2015);
std::cout << ymd << '\n';  // 2015-11-29

答案 1 :(得分:0)

如果MonthCode + YearCode大于或等于DayOfWeek,那么该公式将会停用一周(甚至两周),因为在这种情况下,您将计算{ {1}}来自负面日期。

作为替代方案,如果没有表格,您可以使用例如Zeller's algorithm来计算每月第一天的星期几:

NthOccurenceOfDay