Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Алгоритм нахождения праздничной даты.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Jenya7
Есть RTC.
Код
struct sRTC
{
    uint8_t rtcYear;
    uint8_t rtcMonth;
    uint8_t rtcDay;
    uint8_t rtcDayOfWeek;
    uint8_t rtcHour;
    uint8_t rtcMin;
    uint8_t rtcSec;

};

extern struct sRTC rtc;

Инициализирую
Код
rtc.rtcYear = 2015;
rtc.rtcMonth = 1;
rtc.rtcDay = 29;
rtc.rtcDayOfWeek = 5;
rtc.rtcHour = 12;
rtc.rtcMin = 30;
rtc.rtcSec = 10;


Нужно послать сигнал когда праздник подошел . Скажем 9 Мая. Как это сделать? Думал забить таблицу праздников на 20 лет вперед и каждый час сравнивать текущую дату но подозреваю это не самое лучшее решение.
gerber
Можно отслеживать изменение дня, и в момент изменения дня анализировать праздничную таблицу, один раз в сутки.
Код
static uint8_t nPrevDay = 255;
if(rtc.rtcDay != nPrevDay)
{
  nPrevDay = rtc.rtcDay;

  if( (rtc.rtcDay == 13) && (rtc.rtcDayOfWeek == 5) )
  {
    printf("Пятница 13-е !!!\r\n");
  }
}
Jenya7
если пойти прямым путем то раз в сутки мне нужно перебрать все праздничные даты и сравнить с моей, так я знаю наступила праздничная дата или нет. а что если так. взять первый праздник в году и от него отсчитывать дни. при старте системы посчитать где наша дата по отношению к первому празднику.
и потом обрабатывать случаи. скажем прошло сто дней - значит второй праздник, 150 дней - третий праздник и.т.д.
fider
Видимо можно и так, только с учетом високосного года.
CrimsonPig
Цитата(Jenya7 @ Feb 1 2015, 09:05) *
если пойти прямым путем то раз в сутки мне нужно перебрать все праздничные даты и сравнить с моей, так я знаю наступила праздничная дата или нет. а что если так. взять первый праздник в году и от него отсчитывать дни. при старте системы посчитать где наша дата по отношению к первому празднику.
и потом обрабатывать случаи. скажем прошло сто дней - значит второй праздник, 150 дней - третий праздник и.т.д.


There are many ways to skin a cat. Можно, например, завести битовый массив длинной 365 бит sm.gif Если единичка установлена, то в соотв. день - просто праздник какой-то!
Получается типа однобитной хэш-таблицы. Некоторая проблема возникнет, если на один день приходится несколько праздников.
Jenya7
Цитата(CrimsonPig @ Feb 1 2015, 16:33) *
There are many ways to skin a cat. Можно, например, завести битовый массив длинной 365 бит sm.gif Если единичка установлена, то в соотв. день - просто праздник какой-то!
Получается типа однобитной хэш-таблицы. Некоторая проблема возникнет, если на один день приходится несколько праздников.

мне кажется что работа с таким массивом не отличается от перебора. мне нужна оптимизация по скорости.
CrimsonPig
Цитата(Jenya7 @ Feb 1 2015, 11:15) *
мне кажется что работа с таким массивом не отличается от перебора. мне нужна оптимизация по скорости.


Не понял.. ваши часы не знают, какой по счету день года сегодня ?
Заведите тогда еще и счетчик дней с 1 Января.
toweroff
Цитата(Jenya7 @ Feb 1 2015, 14:15) *
мне нужна оптимизация по скорости.

праздников не так много, массив небольшой с номерами дней.
поиск сделать по бинарному дереву
alexeyv
А что если все праздники отсортировать и в момент перехода на новый день сравнивать только с одной датой - самой ближайшей. При наступлении этой даты - взводить счетчик на следующую ближайшую дату. Ну и раз в полгода добавлять в отсортированную таблицу следующие даты. И никаких переборов.
nill
На эти грабли уже наступали? Или это просто пример с потолка?
Цитата(Jenya7 @ Feb 1 2015, 14:38) *
Код
struct sRTC
{
    uint8_t rtcYear;
};

Код
rtc.rtcYear = 2015;

Grizzzly
Цитата(alexeyv @ Feb 2 2015, 07:35) *
И никаких переборов.

Не понял, откуда берутся переборы?
Не проще ли создать массив uint32_t holidays[12], в котором, как предложил CrimsonPig, будут отмечены единичными битами праздники. В данном случае даже счетчик числа дней от начала года не нужен. По rtcMonth выбираем месяц из массива, по rtcDay выделяем нужный бит и проверяем его на равенство единице.
Jenya7
Цитата(Grizzzly @ Feb 2 2015, 14:23) *
Не понял, откуда берутся переборы?
Не проще ли создать массив uint32_t holidays[12], в котором, как предложил CrimsonPig, будут отмечены единичными битами праздники. В данном случае даже счетчик числа дней от начала года не нужен. По rtcMonth выбираем месяц из массива, по rtcDay выделяем нужный бит и проверяем его на равенство единице.

а почему 12 элементов? тогда нужен второй вектор - дни в месяце.

Цитата(nill @ Feb 2 2015, 12:11) *
На эти грабли уже наступали? Или это просто пример с потолка?

я потом делаю +/- 2000
Grizzzly
Цитата(Jenya7 @ Feb 2 2015, 11:36) *
а почему 12 элементов? тогда нужен второй вектор - дни в месяце.

По числу месяцев. В месяце не может быть больше 31 дня. Поэтому 32 бит в каждом элементе массива вам хватит. Дальше битовыми сдвигами добираетесь до нужного дня.
adnega
Праздники не наступают каждые 10 мс.
Поэтому если есть ограничение по скорости, то нужно процесс вычисления даты разбить на множество шагов.
Например, за один шаг фоном проверять одну дату из массива хоть перебором.
К моменту вызова функции сегодня_праздник() подготовить и выдать мгновенно ответ не составит труда.
WitFed
Мне кажется, что предложение alexeyv было самым сбалансированным, только недожёванным.
Иметь массив из 10-40 (с Днями Пограничника) пар чисел: (месяц, день) не займёт много памяти, ну и переменную i -- позицию, которую мы ждём. А сравнить с текущими 2 полями структуры времени, когда захочется -- недолго. Совпало -- пискнули наружу, инкрементировали i и обнулили её, если "заступ" за границу массива -- и опять ждём... Больше одного раза на совпадение такая схема не сработает -- сразу же начинается ожидание следующего праздника. И праздников не один, чтобы циклить по одному месту. От объёма "праздности" код не зависит.
Вроде ж праздники у нас от года к году не прыгают, чтобы хранить их на 10 лет вперёд ? Ну только если что-то добавится/убавится Думой официально -- так это любую софтину придётся корректировать.
P.S. Единственный минус -- нужно задать правильное значение i при пуске системы, просчитать позицию умозрительно, а то первый "писк" может быть только через год wink.gif
Т.е. для "совсем мозговитости" этого куска программы можно сравнивать текущее время не только с "[i]"-й позицией, но и "[i-1]"-й, и если "не туда попали" стартовой настройкой, то сдвигать её вперёд. Через несколько временных интервалов проверки система придёт в нормальное состояние.
SM
Вообще, храните время в формате unix time или подобном (можно в своем, не в секундах, например, а в минутах). И, соотв., праздники тоже в нем. И все сведется к банальному сравнению на попадание числа в диапазон.

И, вообще, предсказывать праздничные дни будущего, это дело для экстрасенсов, а не для микроконтроллеров. Так как пути мысли госдумы неисповедимы sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.