Skip to content

Commit efb2dcd

Browse files
committed
Added method getFormattedDateTime and keywords
1 parent 0d7162f commit efb2dcd

File tree

3 files changed

+216
-16
lines changed

3 files changed

+216
-16
lines changed

NTPClient.cpp

Lines changed: 178 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,49 @@
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+
2467
NTPClient::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
}
142185
int 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

166328
void NTPClient::end() {
@@ -170,15 +332,19 @@ void NTPClient::end() {
170332
}
171333

172334
void NTPClient::setTimeOffset(int timeOffset) {
173-
this->_timeOffset = timeOffset;
335+
this->_timeOffset = timeOffset;
174336
}
175337

176338
void NTPClient::setUpdateInterval(unsigned long updateInterval) {
177339
this->_updateInterval = updateInterval;
178340
}
179341

342+
void NTPClient::setDateLanguage(const String &dateLanguage) {
343+
this->_dateLanguage = dateLanguage;
344+
}
345+
180346
void NTPClient::setPoolServerName(const char* poolServerName) {
181-
this->_poolServerName = poolServerName;
347+
this->_poolServerName = poolServerName;
182348
}
183349

184350
void NTPClient::sendNTPPacket() {

NTPClient.h

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@
88
#define NTP_PACKET_SIZE 48
99
#define NTP_DEFAULT_LOCAL_PORT 1337
1010

11+
struct DateLanguageData {
12+
const char* shortWeekDays[7];
13+
const char* longWeekDays[7];
14+
const char* shortMonths[12];
15+
const char* longMonths[12];
16+
};
17+
1118
class NTPClient {
1219
private:
1320
UDP* _udp;
21+
String _dateLanguage = "en"; // Default language
1422
bool _udpSetup = false;
1523

1624
const char* _poolServerName = "pool.ntp.org"; // Default time server
@@ -81,7 +89,10 @@ class NTPClient {
8189
*/
8290
bool isTimeSet() const;
8391

92+
int getDayOfWeek() const;
8493
int getDay() const;
94+
int getMonth() const;
95+
int getYear() const;
8596
int getHours() const;
8697
int getMinutes() const;
8798
int getSeconds() const;
@@ -98,9 +109,28 @@ class NTPClient {
98109
void setUpdateInterval(unsigned long updateInterval);
99110

100111
/**
101-
* @return time formatted like `hh:mm:ss`
112+
* @return Date Time string formated. The available format codes are:
113+
%Y: Full year (e.g., 2023)
114+
%y: Last two digits of the year (e.g., 23 for 2023)
115+
%m: Month as a zero-padded decimal number (01 to 12)
116+
%d: Day of the month as a zero-padded decimal number (01 to 31)
117+
%H: Hour (00 to 23) as a zero-padded decimal number
118+
%M: Minute as a zero-padded decimal number (00 to 59)
119+
%S: Second as a zero-padded decimal number (00 to 59)
120+
%a: Abbreviated weekday name according to the current locale
121+
%A: Full weekday name according to the current locale
122+
%w: Weekday as a decimal number (0 for Sunday through 6 for Saturday)
123+
%b: Abbreviated month name according to the current locale
124+
%B: Full month name according to the current locale
125+
%p: "AM" or "PM" based on the hour (Note: This is locale-sensitive and might not be applicable in all languages)
126+
*/
127+
String getFormattedDateTime(const String &format);
128+
129+
/**
130+
* Set language for displaying date. Available languages are 'pt', 'es' and 'en' (default)
131+
* @param dateLanguage
102132
*/
103-
String getFormattedTime() const;
133+
void setDateLanguage(const String &dateLanguage);
104134

105135
/**
106136
* @return time in seconds since Jan. 1, 1970

keywords.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@ update KEYWORD2
1414
forceUpdate KEYWORD2
1515
isTimeSet KEYWORD2
1616
getDay KEYWORD2
17+
getDayOfWeek KEYWORD2
18+
getDay KEYWORD2
19+
getMonth KEYWORD2
20+
getYear KEYWORD2
1721
getHours KEYWORD2
1822
getMinutes KEYWORD2
1923
getSeconds KEYWORD2
20-
getFormattedTime KEYWORD2
24+
getFormattedDateTime KEYWORD2
2125
getEpochTime KEYWORD2
2226
setTimeOffset KEYWORD2
2327
setUpdateInterval KEYWORD2
24-
setPoolServerName KEYWORD2
28+
setPoolServerName KEYWORD2

0 commit comments

Comments
 (0)