Я использую MCP7940 RTC от микрочипа, который требует ввода дня недели как часть обновления RTC с датой. Итак, как мне рассчитать день недели на основе даты, предоставленной пользователем?
Если вы хотите самостоятельно вычислить день недели, вот реализация на C части модуля Perl, который я написал около 20 лет назад. Мне нравится этот алгоритм, потому что он не требует никакого цикла или таблицы длин месяцев. Обратите внимание, что int
s предполагается 32-битным.
/* Returns the number of days to the start of the specified year, taking leap
* years into account, but not the shift from the Julian calendar to the
* Gregorian calendar. Instead, it is as though the Gregorian calendar is
* extrapolated back in time to a hypothetical "year zero".
*/
int leap (int year)
{
return year*365 + (year/4) - (year/100) + (year/400);
}
/* Returns a number representing the number of days since March 1 in the
* hypothetical year 0, not counting the change from the Julian calendar
* to the Gregorian calendar that occured in the 16th century. This
* algorithm is loosely based on a function known as "Zeller's Congruence".
* This number MOD 7 gives the day of week, where 0 = Monday and 6 = Sunday.
*/
int zeller (int year, int month, int day)
{
year += ((month+9)/12) - 1;
month = (month+9) % 12;
return leap (year) + month*30 + ((6*month+5)/10) + day + 1;
}
/* Returns the day of week (1=Monday, 7=Sunday) for a given date.
*/
int dow (int year, int month, int day)
{
return (zeller (year, month, day) % 7) + 1;
}
Согласно даташиту по адресу 0x03 в таблице 4-1 есть поле «День». В конце строки есть краткое описание:
Это означает, что день может быть установлен на любое число от 1 до 7. Вы можете выбрать свой собственный день недели. В системах POSIX понедельник определяется как 1, я думаю, что это хороший стандарт. Тогда вторник = 2; среда = 3; ...
День = 0 не задокументирован, поэтому не используйте его.
В Linux этот номер легко найти с помощью команды date +%u
, которая сегодня отвечает, что сегодня 6
суббота. Если вы хотите рассчитать это локально на своем PIC, вам нужно будет найти C-библиотеку, которая реализует формулу, я верю strftime
, <time.h>
что она делает именно это, но я недостаточно программист на C, чтобы объяснить, как использовать эту конкретную библиотеку. Это широко используемая библиотека, поэтому документацию легко найти.
День недели произвольный . Вы определяете это. Вы можете использовать юлианское воскресенье = день 1. Вы можете использовать понедельник как день 1, потому что воскресенье - 7-й день. Вы можете использовать пятницу в качестве дня 1, потому что это первый день выходных. Вы можете использовать вторник как день 1, потому что вы ненавидите понедельники.
Я предлагаю вам использовать библиотеку RTClib
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
Serial.begin(9600);
delay(3000); // wait for console opening
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, lets set the time!");
// Comment out below lines once you set the date & time.
// Following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// Following line sets the RTC with an explicit date & time
// for example to set January 27 2017 at 12:56 you would call:
// rtc.adjust(DateTime(2017, 1, 27, 12, 56, 0));
}
}
void loop () {
DateTime now = rtc.now();
Serial.println("Current Date & Time: ");
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
Serial.println("Unix Time: ");
Serial.print("elapsed ");
Serial.print(now.unixtime());
Serial.print(" seconds/");
Serial.print(now.unixtime() / 86400L);
Serial.println(" days since 1/1/1970");
// calculate a date which is 7 days & 30 seconds into the future
DateTime future (now + TimeSpan(7,0,0,30));
Serial.println("Future Date & Time (Now + 7days & 30s): ");
Serial.print(future.year(), DEC);
Serial.print('/');
Serial.print(future.month(), DEC);
Serial.print('/');
Serial.print(future.day(), DEC);
Serial.print(' ');
Serial.print(future.hour(), DEC);
Serial.print(':');
Serial.print(future.minute(), DEC);
Serial.print(':');
Serial.print(future.second(), DEC);
Serial.println();
Serial.println();
delay(1000);
}
суперкот
Дэйв Твид