Расчет перехода на летнее время без библиотек и системных вызовов

0

Итак, я кодирую систему с только RTC, содержащим понедельник, день, год, час, минуту, секунду и день недели.

Без хороших библиотек и системных вызовов я пытаюсь создать способ просто рассчитать, является ли это DST или нет на основе правил США и Канады и правила Мексики.

Является ли этот код лучшим способом сделать это для США, где правило "Второе воскресенье марта 2AM до первого воскресенья 2 ноября",

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;
}

А затем в Мексику, где правило - первое воскресенье с 2 апреля по воскресенье до 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;
}

Я предполагаю, что код хорош, и я думаю, что это возможно. Или это может помочь кому-то позже в обсуждении, если оно есть или нет.

  • 0
    Разве детали DST не меняются каждый год в соответствии с прихотями некоторых больших париков? AFAIK, это одна из многих проблем с датой и временем, которую почти невозможно решить с помощью алгоритма, и которую нужно извлечь из базы данных.
  • 0
    @delnan не каждый рядом, даже близко. Тем не менее, правила иногда меняются, поэтому знайте, что ваш код (если вы его жестко запрограммировали таким образом) может в конечном итоге измениться.
Показать ещё 7 комментариев
Теги:
date
time

1 ответ

0

В этом примере используется класс С# 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 AM CST и 1:30 AM CDT от "возврата" "день.

(Я знаю, что ваш код C++, но поскольку вы также отметили этот С#, я предположил, что решение С# было бы приемлемым - это не сложно перевести этот метод в ваш контекст)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню