2121
2222#include " NTPClient.h"
2323
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+
2467NTPClient::NTPClient (UDP& udp) {
2568 this ->_udp = &udp;
2669}
@@ -136,7 +179,7 @@ unsigned long NTPClient::getEpochTime() const {
136179 ((millis () - this ->_lastUpdate ) / 1000 ); // Time since last update
137180}
138181
139- int NTPClient::getDay () const {
182+ int NTPClient::getDayOfWeek () const {
140183 return (((this ->getEpochTime () / 86400L ) + 4 ) % 7 ); // 0 is Sunday
141184}
142185int NTPClient::getHours () const {
@@ -149,18 +192,137 @@ int NTPClient::getSeconds() const {
149192 return (this ->getEpochTime () % 60 );
150193}
151194
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 };
156215
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+ }
159223
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+ }
162284
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;
164326}
165327
166328void NTPClient::end () {
@@ -170,15 +332,19 @@ void NTPClient::end() {
170332}
171333
172334void NTPClient::setTimeOffset (int timeOffset) {
173- this ->_timeOffset = timeOffset;
335+ this ->_timeOffset = timeOffset;
174336}
175337
176338void NTPClient::setUpdateInterval (unsigned long updateInterval) {
177339 this ->_updateInterval = updateInterval;
178340}
179341
342+ void NTPClient::setDateLanguage (const String &dateLanguage) {
343+ this ->_dateLanguage = dateLanguage;
344+ }
345+
180346void NTPClient::setPoolServerName (const char * poolServerName) {
181- this ->_poolServerName = poolServerName;
347+ this ->_poolServerName = poolServerName;
182348}
183349
184350void NTPClient::sendNTPPacket () {
0 commit comments