реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Алгоритм перехода на летнее время.
SpiritDance
сообщение Mar 31 2008, 05:19
Сообщение #1


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Во-первых поздравляю всех с переходом на летнее время. Хорошего всем самочувствия.

Вопрос в следующем, кто-нибудь собственно алгоритм перехода на летнее время и обратно для часов встроенных систем? Если да то помогите либо подробным алгоритмом, либо исходниками пжалста. Надеюсь это не коммерческая тайна. smile.gif


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 06:28
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Не нужно автоматически переводить время. Оставьте эту функцию на усмотрение пользователя. Иначе вохникают большие проблемы в случае когда используется журналирование данных с автоматическим восстановлением при сбоях и поиском по журналу.
А алгоритм при этом очень простой получается: при выводе времени на индикацию, прибавляйте один час к показаниям, если пользователем установлен флаг перехода на летнее время. В моем мобильнике, например, реализовано именно так.
Go to the top of the page
 
+Quote Post
acex2
сообщение Mar 31 2008, 07:21
Сообщение #3


Адепт
****

Группа: Свой
Сообщений: 520
Регистрация: 15-02-05
Пользователь №: 2 656



Цитата(SpiritDance @ Mar 31 2008, 09:19) *
Во-первых поздравляю всех с переходом на летнее время. Хорошего всем самочувствия.

Вопрос в следующем, кто-нибудь собственно алгоритм перехода на летнее время и обратно для часов встроенных систем? Если да то помогите либо подробным алгоритмом, либо исходниками пжалста. Надеюсь это не коммерческая тайна. smile.gif


Вот тут подробно, по странам: http://www.worldtimezone.com/daylight.html
Вкратце: "В России и в Европе переход на летнее время осуществляется в последнее воскресенье марта в 2:00 переводом часовых стрелок на 1 час вперед, а обратный переход осуществляется в последнее воскресенье октября в 3:00 переводом стрелок на 1 час назад."
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Mar 31 2008, 08:36
Сообщение #4


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Вот алгоритм вычисление собственно последнего дня недели в месяце в текущем году и интересует.

Журналирование данных ведется и временной поиск есть, думал избежать проблем с запретом перевода времени пока с последней журнальной записи не пройдет час. Еще подумаю.
на откуп пользователю отдать не могу, так как во-превых по времени определяется валидность sms? во вторых может возникнуть путаница с пониманием что в устройстве всегда записывается "зимнее" время.


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
Andrew2000
сообщение Mar 31 2008, 10:35
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 421
Регистрация: 25-12-04
Пользователь №: 1 675



Цитата(SpiritDance @ Mar 31 2008, 12:36) *
Вот алгоритм вычисление собственно последнего дня недели в месяце в текущем году и интересует.

Для учета летнего/зимнего времени можно определить следующие переменные:

char saving-starts[3] = {p1,p2,p3};
char saving-ends[3] = {p1,p2,p3};
char time-offset = p4;
char saving-starts-time = p5;
char saving-ends-time = p6;

Параметры: p1 – какой день: 1 – первый, -1 – последний день недели месяца; p2 – день недели: 0 – воскресенье; p3 – месяц; p4 – разница во времени в минутах при переходе; p5, p6 – число минут после полуночи, когда переводить стрелки.

Переход на летнее время - Последнее воскресенье марта 2 часа ночи.
Переход на зимнее время - Последнее воскресенье октября 3 часа ночи.

saving-starts[3] = {1,0,4}; // последнее воскресенье марта
saving-ends[3] = {-1,0,10}; //последнее воскресенье октября
time-offset = 60; //1 час
saving-starts-time = 120; //2 часа ночи
saving-ends-time = 180; //3 часа ночи

Алгоритм перевода стрелок осенью:
1. На основании системных переменных знаем время перехода (tm_sec, tm_min, tm_hour);
2. Найдем (mktime) номер дня недели (tm_wday) для даты <сего года>.10.31 00:00:00 (последний день месяца);
3. dD := <номер дня недели <сего года>.10.31> – <номер дня недели перехода (из системной переменной)>; (учесть переход через 0);
4. ЧИСЛО ПЕРЕХОДА (tm_mday) = 31- dD;
5.Зная число (см. п.4) месяц (tm_mon) и год (tm_year) перехода (из системной переменной) и время перехода (см. п.1) определяем (time_t mktime(struct tm* )) точное время этого события в time_t формате.
Затем сверяем его с текущим временем.

Время перехода определяем при включении питания и при коррекции времени.

Примечание: в п.2,3,4 жестко записано 31, но нужно учитывать 30/31, если, вдруг, будет не октябрь и не март.

!!! аппаратные часы _всегда_ должны считать время в UTC, а учет летнего времени можно учитывать для отображения, журналов, и т.д.
Go to the top of the page
 
+Quote Post
rezident
сообщение Mar 31 2008, 11:25
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Andrew2000 @ Mar 31 2008, 16:35) *
!!! аппаратные часы _всегда_ должны считать время в UTC, а учет летнего времени можно учитывать для отображения, журналов, и т.д.
Угу. Я об этом же выше и толкую. Только в журнал тогда нужно писать лишь флаг-признак перехода на летнее время, а не собственно "летнее" время. Чтобы избежать глюков при индексировании и поиске почасовых записей.
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Mar 31 2008, 11:42
Сообщение #7


Дух погибшего транзистора
****

Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288



Спасибо.


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
umup
сообщение Apr 2 2008, 20:11
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 226
Регистрация: 2-06-06
Пользователь №: 17 720



я делал (в программных часах на Меге 8) просто таблицу чисел марта/октября, соответствующих переходу (с 2000 по 203x год - всего 64 байта, думаю само вычисление числа займет больше).

Функция rtc_increment вызывается каждую секунду в обработчике прерывания часового кварца.
Флаги flag_rtc_sec_pass, flag_rtc_min_pass, flag_rtc_hr_pass используются в других частях программы для синхронизации с секундными, минутными, часовыми событиями (в конце основного цикла обнуляются).
Флаги flag_rtc_corrected и flag_rtc_corrected_forw - для улавливания события коррекции.

ul_rtc.h :

Код
/** \addtogroup group_rtc RTC structure/functions (структура и функции для работы с часами реального времени)
  */

#if ((!defined(ul_c_rtc_included)) || (defined __DOXYGEN__))

#define ul_c_rtc_included 1    /**< \brief module inclusion flag<br />флаг включения модуля \ingroup group_rtc */

#include "ul_misc.h"         /*include misc definitions/functions types*/

/** \brief RTC structure<br />структура часов \ingroup group_rtc */
typedef struct
{u8 sec;      /**< \brief seconds (0..59)   <br />секунды (0..59)       \ingroup group_rtc */
u8 min;      /**< \brief minutes (0..59)   <br />минуты (0..59)        \ingroup group_rtc */
u8 hr;       /**< \brief hours (0..23)     <br />часы (0..23)          \ingroup group_rtc */
u8 date;     /**< \brief date (1..31)      <br />дата (1..31)          \ingroup group_rtc */
u8 month;    /**< \brief month (1..12)     <br />месяц (1..12)         \ingroup group_rtc */
u16 year;    /**< \brief year (1900..2100) <br />год (1900..2100)      \ingroup group_rtc */
u8 flags;    /**< \brief RTC flags         <br />флаги RTC             \ingroup group_rtc */
u16 crc;     /**< \brief crc of structure  <br />контр.сумма структуры \ingroup group_rtc */
}struct_rtc;

#define flag_rtc_sec_pass       0x01 /**< \brief =1 every second passed <br />=1 каждую секунду \ingroup group_rtc */
#define flag_rtc_min_pass       0x02 /**< \brief =1 every minute passed <br />=1 каждую минуту \ingroup group_rtc */
#define flag_rtc_hr_pass        0x04 /**< \brief =1 every hour passed   <br />=1 каждый час \ingroup group_rtc */
#define flag_rtc_corrected      0x20 /**< \brief =1 if was time correction <br />=1 если была коррекция на летнее/зимнее время \ingroup group_rtc */
#define flag_rtc_corrected_forw 0x40 /**< \brief =1 if was hour-forward time correction (otherwise hour-backward)<br />=1 если была коррекция на час вперед (иначе на час назад) \ingroup group_rtc */
#define flag_rtc_correction     0x80 /**< \brief =1 for auto-correction <br />=1 для автоматического перехода на зимнее/летнее время \ingroup group_rtc */

/** \brief increment time of RTC structure by 1 second<br />увеличить время в структуре часов на 1 секунду \ingroup group_rtc */
inline void rtc_increment(void *rtc_data);

#endif



ul_rtc.c :

Код
#include "ul_rtc.h"  /*include RTC header*/

#if (defined(ul_c_use_gccavr))
#include <avr/pgmspace.h>     /*Program memory usage for AVR-GCC*/
#endif

#if (!defined(rtc_corr_dates_table))
#if (defined(ul_c_use_gccavr))
  u8 rtc_corr_dates_table[][32] PROGMEM = {{29,28,27,26,31,30,29,28,26,25,31,30,28,27,26,25,30,29,28,27,25,31,30,29,27,26,
25,31,29,28,27,26},
  {26,25,31,30,28,27,26,25,30,29,28,27,25,31,30,29,27,26,25,31,29,28,27,26,31
,30,29,28,26,25,31,30}
};
#else
  u8 rtc_corr_dates_table[][32]         = {{29,28,27,26,31,30,29,28,26,25,31,30,28,27,26,25,30,29,28,27,25,31,30,29,27,26,
25,31,29,28,27,26},
  {26,25,31,30,28,27,26,25,30,29,28,27,25,31,30,29,27,26,25,31,29,28,27,26,31
,30,29,28,26,25,31,30}
};
#endif
#endif

inline void rtc_increment(void *rtc_data)
{u8 u8_01, u8_02;
u8_01 = (*((struct_rtc *)rtc_data)).month;
u8_02 = (*((struct_rtc *)rtc_data)).date;
(*((struct_rtc *)rtc_data)).flags |= flag_rtc_sec_pass;  /*set second passed flag*/
if (++((*((struct_rtc *)rtc_data)).sec) == 60)          /*process seconds overflow*/
{(*((struct_rtc *)rtc_data)).sec = 0;
  (*((struct_rtc *)rtc_data)).flags |= flag_rtc_min_pass; /*set minute passed flag*/
  if (++((*((struct_rtc *)rtc_data)).min) == 60)         /*process minutes overflow*/
  {(*((struct_rtc *)rtc_data)).min = 0;
   (*((struct_rtc *)rtc_data)).flags |= flag_rtc_hr_pass; /*set hour passed flag*/
   if (++((*((struct_rtc *)rtc_data)).hr) == 24)         /*process hours overflow*/
   {(*((struct_rtc *)rtc_data)).hr = 0;
    u8_02++; /*calculate next date*/
    if (u8_02 == 32) {u8_01++; u8_02 = 1;}
    else if (u8_02 == 31)
    {if ((u8_01 == 4) || (u8_01 == 6) || (u8_01 == 9) || (u8_01 == 11))
     {u8_01++;
      u8_02 = 1;
     }
    }else if (u8_02 == 30)
     {if (u8_01==2) {u8_01++; u8_02 = 1;}
     }else if (u8_02 == 29)
      {if ((u8_01 == 2) && (((*((struct_rtc *)rtc_data)).year) & 3))
       {u8_01++;
        u8_02 = 1;
       }
      }
    /*month overflow*/
    if (u8_01 == 13)
    {u8_01 = 1;
     ((*((struct_rtc *)rtc_data)).year)++;
    }
   }
  }
}
(*((struct_rtc *)rtc_data)).month = u8_01;
(*((struct_rtc *)rtc_data)).date = u8_02;

/*if needed, do time auto correction*/
if ((*((struct_rtc *)rtc_data)).flags & flag_rtc_correction)
{/*every last sunday of march (hour++) and october (hour--) at 4 a.m.*/
  if (((u8_01 == 10) || (u8_01 == 3)) && (u8_02 > 24) &&
      ((*((struct_rtc *)rtc_data)).hr == 4) && ((*((struct_rtc *)rtc_data)).min == 0) &&
      ((*((struct_rtc *)rtc_data)).sec == 0))
  {u8 u8_03;
   /*get correction date*/
   u8_03 = ((u8)((*((struct_rtc *)rtc_data)).year)) & 0x1f; /*table index*/
   #if (defined(ul_c_use_gccavr))
    u8_03 = pgm_read_byte(&(rtc_corr_dates_table[u8_01 & 1][u8_03]));
   #else
    u8_03 = rtc_corr_dates_table[u8_01 & 1][u8_03];
   #endif
   /*if date is correct, do time correction*/
   if (u8_02 == u8_03)
   {(*((struct_rtc *)rtc_data)).flags |= flag_rtc_corrected; /*set correction flag*/
    if (u8_01 == 3)
    {(*((struct_rtc *)rtc_data)).hr++;
     (*((struct_rtc *)rtc_data)).flags |= flag_rtc_corrected_forw; /*forward correction*/
    }else (*((struct_rtc *)rtc_data)).hr--;
   }
  }
}
}


Сообщение отредактировал umup - Apr 2 2008, 20:36
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd June 2025 - 21:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01441 секунд с 7
ELECTRONIX ©2004-2016