在没有库和系统调用的情况下计算夏令时

时间:2013-12-26 21:00:04

标签: c# c++ date time

所以,我正在编写一个只有一个包含星期一,日,年,小时,分钟,秒和星期几的RTC的系统。

如果没有好的库和系统调用,我正在尝试根据美国/加拿大规则和墨西哥规则创建一种简单计算是否为夏令时的方法。

这段代码是美国的最佳方式,规则是“3月2日凌晨2点到11月2日凌晨1点”

switch (TestDateTime->Month)
{
    case 1:
    case 2:
    case 12:
        // January, February and December are definitely NOT DST months
        u8RetVal = FALSE;
        break;

    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
        // April, May, June, July, August, September, October are definitely FULL DST months
        u8RetVal = TRUE;
        break;

    case 3:
        // At this point, this is March is a partial DST month
        i8PreviousSunday = TestDateTime->DayOfMonth - TestDateTime->DayOfWeek;

        // In march, we are DST if our previous sunday was on or after the 8th.
        if (i8PreviousSunday >= 8)
        {
            // So if it is the 2nd week of March and the day is a Sunday, check the time for less than 2AM, if so, it isn't DST yet
            if ((TestDateTime->DayOfMonth >= 8) && (TestDateTime->DayOfMonth <= 14) && (TestDateTime->DayOfWeek == 0) && (TestDateTime->Hours < 2))
            {
                u8RetVal = FALSE;
            }
            else
            {
                u8RetVal = TRUE;
            }
        }
        else
        {
            u8RetVal = FALSE;
        }
        break;

    case 11:
        // At this point, this is November is a partial DST month
        i8PreviousSunday = TestDateTime->DayOfMonth - TestDateTime->DayOfWeek;

        // In november we must be before the first sunday to be in DST.  That means the previous sunday must be before the 1st.
        if (i8PreviousSunday <= 0)
        {
            // This falls on the Monday-Saturday before the first Sunday, so we are still DST
            u8RetVal = TRUE;
        }
        else
        {
            // This falls on the first Sunday and later.  So, a catch for the Sunday of the first week, if not 2AM yet, we are still DST.
            if ((TestDateTime->DayOfMonth >= 1) && (TestDateTime->DayOfMonth <= 7) && (TestDateTime->DayOfWeek == 0) && (TestDateTime->Hours < 2))
            {
                u8RetVal = TRUE;
            }
            else
            {
                u8RetVal = FALSE;
            }
        }
        break;

    default:
        // Invalid Month
        u8RetVal = FALSE;
        break;
}

然后在墨西哥,规则是4月2日的第一个星期日到10月2日的上个星期日。

switch (TestDateTime->Month)
{
    case 1:
    case 3:
    case 2
    case 11:
    case 12:
        // January, February, March, November and December are definitely NOT DST months
        u8RetVal = FALSE;
        break;

    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
        // May, June, July, August, September are definitely FULL DST months
        u8RetVal = TRUE;
        break;

    case 4:
        // At this point, this is April is a partial DST month
        i8PreviousSunday = TestDateTime->DayOfMonth - TestDateTime->DayOfWeek;

        // In march, we are DST if our previous sunday was on or after the 1st.
        if (i8PreviousSunday >= 1)
        {
            // So if it is the 2nd week of March and the day is a Sunday, check the time for less than 2AM, if so, it isn't DST yet
            if ((TestDateTime->DayOfMonth >= 1) && (TestDateTime->DayOfMonth <= 7) && (TestDateTime->DayOfWeek == 0) && (TestDateTime->Hours < 2))
            {
                u8RetVal = FALSE;
            }
            else
            {
                u8RetVal = TRUE;
            }
        }
        else
        {
            u8RetVal = FALSE;
        }
        break;

    case 10:
        // At this point, this is October is a partial DST month
        i8PreviousSunday = TestDateTime->DayOfMonth - TestDateTime->DayOfWeek;

        // In October we must be before the last Sunday, which will always be one of the last 7 days
        if (i8PreviousSunday <= 24)
        {
            // This falls on the Monday-Saturday before the first Sunday, so we are still DST
            u8RetVal = TRUE;
        }
        else
        {
            // This falls on the first Sunday and later.  So, a catch for the Sunday of the first week, if not 2AM yet, we are still DST.
            if ((TestDateTime->DayOfMonth >= 25) && (TestDateTime->DayOfMonth <= 31) && (TestDateTime->DayOfWeek == 0) && (TestDateTime->Hours < 2))
            {
                u8RetVal = TRUE;
            }
            else
            {
                u8RetVal = FALSE;
            }
        }
        break;

    default:
        // Invalid Month
        u8RetVal = FALSE;
        break;
}

我假设代码是好的,我认为它可能是。或者它可以在以后通过讨论帮助其他人。如果它是或不是。

1 个答案:

答案 0 :(得分:0)

此示例使用C#的DateTime类,但也应该使用您的代码:

public static DateTime GetDay(int year, int month, int ordinal,
                              DayOfWeek dayOfWeek, bool fromStart)
{
    DateTime result = new DateTime(year, month, 1);
    if (!fromStart)
        result = result.AddMonths(1).AddDays(-1);
    int mult = fromStart ? 1 : -1;
    for (; result.DayOfWeek != dayOfWeek; result = result.AddDays(1 * mult));
    for (int i = 1; i < ordinal; result = result.AddDays(7 * mult), i++);
    return result;
}

// use like this
// meaning: in 2013, in March, find the second Sunday, from the beginning
GetDay(2013, 3, 2, DayOfWeek.Sunday, true); // US start, Mar 10
GetDay(2013, 11, 1, DayOfWeek.Sunday, true); // US end, Nov 3
GetDay(2013, 4, 1, DayOfWeek.Sunday, true); // MX start, Apr 7
// meaning: in 2013, in October, find the first Sunday, from the end
GetDay(2013, 10, 1, DayOfWeek.Sunday, false); // MX end, Oct 27

然后,一些简单的日期比较将告诉您目标时间是否为DST,DST周围的小时数除外。这变得更复杂,你真的需要存储比你说的更多的信息,例如存储UTC时间戳,然后在需要时将其转换,例如区分美国中部时间凌晨1:30和CDT凌晨1:30“退回”日。

(我知道你的代码是C ++,但是你也标记了这个C#,我认为C#解决方案是可以接受的 - 将这个方法翻译成你的上下文应该不难)