AceTime 2.4.0 Date and time classes for Arduino that support timezones from the TZ Database.

ZoneProcessor.cpp
1 /*
2 * MIT License
3 * Copyright (c) 2019 Brian T. Park
4 */
5
6 #include <string.h> // strchr(), strncpy(), memcpy()
7 #include <AceCommon.h> // copyReplaceString(), PrintStr
8 #include "ZoneProcessor.h"
9 #include "common/DateConv.h" // secondsToHms()
10
11 namespace ace_time {
12 namespace internal {
13
14 MonthDay calcStartDayOfMonth(int16_t year, uint8_t month,
15 uint8_t onDayOfWeek, int8_t onDayOfMonth) {
16 if (onDayOfWeek == 0) return {month, (uint8_t) onDayOfMonth};
17
18 if (onDayOfMonth >= 0) {
19 // Convert "last{Xxx}" to "last{Xxx}>={daysInMonth-6}".
20 uint8_t daysInMonth = LocalDate::daysInMonth(year, month);
21 if (onDayOfMonth == 0) {
22 onDayOfMonth = daysInMonth - 6;
23 }
24
25 auto limitDate = LocalDate::forComponents(year, month, onDayOfMonth);
26 uint8_t dayOfWeekShift = (onDayOfWeek - limitDate.dayOfWeek() + 7) % 7;
27 uint8_t day = (uint8_t) (onDayOfMonth + dayOfWeekShift);
28 if (day > daysInMonth) {
29 // TODO: Support shifting from Dec to Jan of following year.
30 day -= daysInMonth;
31 month++;
32 }
33 return {month, day};
34 } else {
35 onDayOfMonth = -onDayOfMonth;
36 auto limitDate = LocalDate::forComponents(year, month, onDayOfMonth);
37 int8_t dayOfWeekShift = (limitDate.dayOfWeek() - onDayOfWeek + 7) % 7;
38 int8_t day = onDayOfMonth - dayOfWeekShift;
39 if (day < 1) {
40 // TODO: Support shifting from Jan to Dec of the previous year.
41 month--;
42 uint8_t daysInPrevMonth = LocalDate::daysInMonth(year, month);
43 day += daysInPrevMonth;
44 }
45 return {month, (uint8_t) day};
46 }
47 }
48
49 void createAbbreviation(
50 char* dest,
51 uint8_t destSize,
52 const char* format,
53 int32_t stdSeconds,
54 int32_t dstSeconds,
55 const char* letterString) {
56
57 // Check if FORMAT is a '%z'
58 if (*format == '\0') {
59 int32_t totalSeconds = stdSeconds + dstSeconds;
60 uint32_t secs = (totalSeconds >= 0) ? totalSeconds : -totalSeconds;
61 ace_common::PrintStr<internal::kAbbrevSize> buf;
62 uint16_t hh, mm, ss;
63 secondsToHms(secs, &hh, &mm, &ss);
64 buf.print((totalSeconds >= 0) ? '+' : '-');
65 ace_common::printPad2To(buf, hh, '0'); // pad with leading '0'
66 if (mm != 0 || ss != 0) {
67 ace_common::printPad2To(buf, mm, '0');
68 }
69 if (ss != 0) {
70 ace_common::printPad2To(buf, ss, '0');
71 }
72 strncpy(dest, buf.cstr(), internal::kAbbrevSize);
73 dest[destSize - 1] = '\0';
74
75 // Check if FORMAT contains a '%s'.
76 } else if (strchr(format, '%') != nullptr) {
77 // Check if RULES column empty, therefore no 'letter'
78 if (letterString == nullptr) {
79 strncpy(dest, format, destSize - 1);
80 dest[destSize - 1] = '\0';
81 } else {
82 // Copy `letterString` into a local buffer, in case `letterString` is
83 // the same as `dest.
84 char letter[internal::kAbbrevSize];
85 if (letterString) {
86 strncpy(letter, letterString, internal::kAbbrevSize - 1);
87 letter[internal::kAbbrevSize - 1] = '\0';
88 } else {
89 letter[0] = '\0';
90 }
91
92 ace_common::copyReplaceString(dest, destSize, format, '%', letter);
93 }
94 } else {
95 const char* slashPos = strchr(format, '/');
96 if (slashPos != nullptr) {
97 if (dstSeconds == 0) {
98 uint8_t headLength = (slashPos - format);
99 if (headLength >= destSize) headLength = destSize - 1;
100 memcpy(dest, format, headLength);
101 dest[headLength] = '\0';
102 } else {
103 uint8_t tailLength = strlen(slashPos+1);
104 if (tailLength >= destSize) tailLength = destSize - 1;
105 memcpy(dest, slashPos+1, tailLength);
106 dest[tailLength] = '\0';
107 }
108 } else {
109 // Just copy the FORMAT disregarding dstSeconds and letterString.
110 strncpy(dest, format, destSize - 1);
111 dest[destSize - 1] = '\0';
112 }
113 }
114 }
115
116 } // internal
117 } // ace_time
ace_time::LocalDate::forComponents
static LocalDate forComponents(int16_t year, uint8_t month, uint8_t day)
Factory method using separated year, month and day fields.
Definition: LocalDate.h:153
ace_time::LocalDate::daysInMonth
static uint8_t daysInMonth(int16_t year, uint8_t month)
Return the number of days in the given (year, month).
Definition: LocalDate.h:133