21
21
22
22
#include " NTPClient.h"
23
23
24
+ const DateLanguageData EnglishData = {
25
+ {" Sun" , " Mon" , " Tue" , " Wed" , " Thu" , " Fri" , " Sat" },
26
+ {" Sunday" , " Monday" , " Tuesday" , " Wednesday" , " Thursday" , " Friday" , " Saturday" },
27
+ {" Jan" , " Feb" , " Mar" , " Apr" , " May" , " Jun" , " Jul" , " Aug" , " Sep" , " Oct" , " Nov" , " Dec" },
28
+ {" January" , " February" , " March" , " April" , " May" , " June" , " July" , " August" , " September" , " October" , " November" , " December" }
29
+ };
30
+
31
+ const DateLanguageData SpanishData = {
32
+ {" Dom" , " Lun" , " Mar" , " Mié" , " Jue" , " Vie" , " Sáb" },
33
+ {" Domingo" , " Lunes" , " Martes" , " Miércoles" , " Jueves" , " Viernes" , " Sábado" },
34
+ {" Ene" , " Feb" , " Mar" , " Abr" , " May" , " Jun" , " Jul" , " Ago" , " Sep" , " Oct" , " Nov" , " Dic" },
35
+ {" Enero" , " Febrero" , " Marzo" , " Abril" , " Mayo" , " Junio" , " Julio" , " Agosto" , " Septiembre" , " Octubre" , " Noviembre" , " Diciembre" }
36
+ };
37
+
38
+ const DateLanguageData PortugueseData = {
39
+ {" Dom" , " Seg" , " Ter" , " Qua" , " Qui" , " Sex" , " Sáb" },
40
+ {" Domingo" , " Segunda-feira" , " Terça-feira" , " Quarta-feira" , " Quinta-feira" , " Sexta-feira" , " Sábado" },
41
+ {" Jan" , " Fev" , " Mar" , " Abr" , " Mai" , " Jun" , " Jul" , " Ago" , " Set" , " Out" , " Nov" , " Dez" },
42
+ {" Janeiro" , " Fevereiro" , " Março" , " Abril" , " Maio" , " Junho" , " Julho" , " Agosto" , " Setembro" , " Outubro" , " Novembro" , " Dezembro" }
43
+ };
44
+
45
+ // Language map definition
46
+ const struct LanguageMap {
47
+ const char * code;
48
+ const DateLanguageData* data;
49
+ } languageMap[] = {
50
+ {" en" , &EnglishData},
51
+ {" es" , &SpanishData},
52
+ {" pt" , &PortugueseData}
53
+ // Add new languages here
54
+ };
55
+ const int languageMapSize = sizeof (languageMap) / sizeof (LanguageMap);
56
+
57
+ // Function to find language data by code
58
+ const DateLanguageData* findLanguageData (const String& code) {
59
+ for (int i = 0 ; i < languageMapSize; ++i) {
60
+ if (code == languageMap[i].code ) {
61
+ return languageMap[i].data ;
62
+ }
63
+ }
64
+ return &EnglishData; // Default to English if not found
65
+ }
66
+
24
67
NTPClient::NTPClient (UDP& udp) {
25
68
this ->_udp = &udp;
26
69
}
@@ -136,7 +179,7 @@ unsigned long NTPClient::getEpochTime() const {
136
179
((millis () - this ->_lastUpdate ) / 1000 ); // Time since last update
137
180
}
138
181
139
- int NTPClient::getDay () const {
182
+ int NTPClient::getDayOfWeek () const {
140
183
return (((this ->getEpochTime () / 86400L ) + 4 ) % 7 ); // 0 is Sunday
141
184
}
142
185
int NTPClient::getHours () const {
@@ -149,18 +192,137 @@ int NTPClient::getSeconds() const {
149
192
return (this ->getEpochTime () % 60 );
150
193
}
151
194
152
- String NTPClient::getFormattedTime () const {
153
- unsigned long rawTime = this ->getEpochTime ();
154
- unsigned long hours = (rawTime % 86400L ) / 3600 ;
155
- String hoursStr = hours < 10 ? " 0" + String (hours) : String (hours);
195
+ int NTPClient::getDay () const {
196
+ long days = this ->getEpochTime () / 86400L ;
197
+ int fullYears = days / 365 ;
198
+ int overDays = days % 365 ;
199
+
200
+ // Adjust for leap years
201
+ int leapYears = (fullYears + 1 ) / 4 ; // +1 because year 0 (1970) is not a leap year
202
+ if (leapYears > overDays) {
203
+ fullYears--;
204
+ }
205
+
206
+ int currentYear = 1970 + fullYears;
207
+
208
+ // Check if current year is a leap year
209
+ bool thisYearIsLeap = (currentYear % 4 == 0 && (currentYear % 100 != 0 || currentYear % 400 == 0 ));
210
+
211
+ // Calculate day of the year
212
+ int dayOfYear = (days - ((fullYears * 365 ) + leapYears)) + 1 ; // +1 to convert from 0-based to 1-based
213
+
214
+ int daysInMonth[12 ] = {31 , 28 + thisYearIsLeap, 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
156
215
157
- unsigned long minutes = (rawTime % 3600 ) / 60 ;
158
- String minuteStr = minutes < 10 ? " 0" + String (minutes) : String (minutes);
216
+ int monthDay = dayOfYear;
217
+ for (int month = 0 ; month < 12 ; month++) {
218
+ if (monthDay <= daysInMonth[month]) {
219
+ return monthDay; // Correct day of the month
220
+ }
221
+ monthDay -= daysInMonth[month];
222
+ }
159
223
160
- unsigned long seconds = rawTime % 60 ;
161
- String secondStr = seconds < 10 ? " 0" + String (seconds) : String (seconds);
224
+ return -1 ; // Error case, should not happen
225
+ }
226
+
227
+ int NTPClient::getMonth () const {
228
+ long days = this ->getEpochTime () / 86400L ; // Total days since epoch
229
+ int fullYears = 0 ;
230
+ int year = 1970 ;
231
+
232
+ // Correctly account for leap years in the loop
233
+ while (days > 365 ) {
234
+ if ((year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0 )) {
235
+ if (days > 366 ) {
236
+ days -= 366 ;
237
+ year++;
238
+ } else {
239
+ break ; // Leap year but not enough days to complete the year
240
+ }
241
+ } else {
242
+ days -= 365 ;
243
+ year++;
244
+ }
245
+ }
246
+
247
+ bool thisYearIsLeap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 ));
248
+ int daysInMonth[12 ] = {31 , 28 + thisYearIsLeap, 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };
249
+
250
+ int month = 0 ;
251
+ for (month = 0 ; month < 12 ; month++) {
252
+ if (days < daysInMonth[month]) {
253
+ break ; // Found the current month
254
+ }
255
+ days -= daysInMonth[month];
256
+ }
257
+
258
+ return month + 1 ; // Month is 1-based
259
+ }
260
+
261
+ int NTPClient::getYear () const {
262
+ long days = this ->getEpochTime () / 86400L ; // Total days since epoch
263
+ int year = 1970 ;
264
+
265
+ while (days > 365 ) {
266
+ if ((year % 4 == 0 && year % 100 != 0 ) || (year % 400 == 0 )) {
267
+ // Leap year
268
+ if (days > 366 ) {
269
+ days -= 366 ;
270
+ year += 1 ;
271
+ } else {
272
+ // If days <= 366 in a leap year, then we've found the current year
273
+ break ;
274
+ }
275
+ } else {
276
+ // Not a leap year
277
+ days -= 365 ;
278
+ year += 1 ;
279
+ }
280
+ }
281
+
282
+ return year;
283
+ }
162
284
163
- return hoursStr + " :" + minuteStr + " :" + secondStr;
285
+ String NTPClient::getFormattedDateTime (const String& format) {
286
+ String result;
287
+ bool escape = false ;
288
+
289
+ const DateLanguageData* langData = findLanguageData (this ->_dateLanguage );
290
+
291
+ for (char c : format) {
292
+ if (c == ' %' ) {
293
+ if (escape) {
294
+ result += c; // Literal '%' character
295
+ escape = false ;
296
+ } else {
297
+ escape = true ;
298
+ }
299
+ continue ;
300
+ }
301
+
302
+ if (escape) {
303
+ switch (c) {
304
+ case ' Y' : result += String (this ->getYear ()); break ;
305
+ case ' y' : result += String (this ->getYear ()).substring (2 ); break ;
306
+ case ' m' : result += (this ->getMonth () < 10 ? " 0" : " " ) + String (this ->getMonth ()); break ;
307
+ case ' d' : result += (this ->getDay () < 10 ? " 0" : " " ) + String (this ->getDay ()); break ;
308
+ case ' H' : result += (this ->getHours () < 10 ? " 0" : " " ) + String (this ->getHours ()); break ;
309
+ case ' M' : result += (this ->getMinutes () < 10 ? " 0" : " " ) + String (this ->getMinutes ()); break ;
310
+ case ' S' : result += (this ->getSeconds () < 10 ? " 0" : " " ) + String (this ->getSeconds ()); break ;
311
+ case ' a' : result += langData->shortWeekDays [this ->getDayOfWeek ()]; break ;
312
+ case ' A' : result += langData->longWeekDays [this ->getDayOfWeek ()]; break ;
313
+ case ' w' : result += String (this ->getDayOfWeek ()); break ;
314
+ case ' b' : result += langData->shortMonths [this ->getMonth () - 1 ]; break ;
315
+ case ' B' : result += langData->longMonths [this ->getMonth () - 1 ]; break ;
316
+ case ' p' : result += (this ->getHours () < 12 ? " AM" : " PM" ); break ; // Note: Consider locale for AM/PM
317
+ default : result += " %" + String (c); // Unsupported format code
318
+ }
319
+ escape = false ;
320
+ } else {
321
+ result += c;
322
+ }
323
+ }
324
+
325
+ return result;
164
326
}
165
327
166
328
void NTPClient::end () {
@@ -170,15 +332,19 @@ void NTPClient::end() {
170
332
}
171
333
172
334
void NTPClient::setTimeOffset (int timeOffset) {
173
- this ->_timeOffset = timeOffset;
335
+ this ->_timeOffset = timeOffset;
174
336
}
175
337
176
338
void NTPClient::setUpdateInterval (unsigned long updateInterval) {
177
339
this ->_updateInterval = updateInterval;
178
340
}
179
341
342
+ void NTPClient::setDateLanguage (const String &dateLanguage) {
343
+ this ->_dateLanguage = dateLanguage;
344
+ }
345
+
180
346
void NTPClient::setPoolServerName (const char * poolServerName) {
181
- this ->_poolServerName = poolServerName;
347
+ this ->_poolServerName = poolServerName;
182
348
}
183
349
184
350
void NTPClient::sendNTPPacket () {
0 commit comments