date_time.c
Go to the documentation of this file.
1 /**
2  * @file date_time.c
3  * @brief Date and time management
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 2.5.4
27  **/
28 
29 //Dependencies
30 #include <stdio.h>
31 #include <string.h>
32 #include "date_time.h"
33 
34 #if defined(_WIN32)
35  #include <time.h>
36 #endif
37 
38 //Days
39 static const char days[8][10] =
40 {
41  "",
42  "Monday",
43  "Tuesday",
44  "Wednesday",
45  "Thursday",
46  "Friday",
47  "Saturday",
48  "Sunday"
49 };
50 
51 //Months
52 static const char months[13][10] =
53 {
54  "",
55  "January",
56  "February",
57  "March",
58  "April",
59  "May",
60  "June",
61  "July",
62  "August",
63  "September",
64  "October",
65  "November",
66  "December"
67 };
68 
69 
70 /**
71  * @brief Format system time
72  * @param[in] time System time
73  * @param[out] str NULL-terminated string representing the specified time
74  * @return Pointer to the formatted string
75  **/
76 
78 {
79  uint16_t hours;
80  uint8_t minutes;
81  uint8_t seconds;
82  uint16_t milliseconds;
83  static char_t buffer[24];
84 
85  //Retrieve milliseconds
86  milliseconds = time % 1000;
87  time /= 1000;
88  //Retrieve seconds
89  seconds = time % 60;
90  time /= 60;
91  //Retrieve minutes
92  minutes = time % 60;
93  time /= 60;
94  //Retrieve hours
95  hours = time;
96 
97  //The parameter is optional
98  if(str == NULL)
99  {
100  str = buffer;
101  }
102 
103  //Format system time
104  if(hours > 0)
105  {
106  osSprintf(str, "%" PRIu16 "h %02" PRIu8 "min %02" PRIu8 "s %03" PRIu16 "ms",
107  hours, minutes, seconds, milliseconds);
108  }
109  else if(minutes > 0)
110  {
111  osSprintf(str, "%" PRIu8 "min %02" PRIu8 "s %03" PRIu16 "ms",
112  minutes, seconds, milliseconds);
113  }
114  else if(seconds > 0)
115  {
116  osSprintf(str, "%" PRIu8 "s %03" PRIu16 "ms", seconds, milliseconds);
117  }
118  else
119  {
120  osSprintf(str, "%" PRIu16 "ms", milliseconds);
121  }
122 
123  //Return a pointer to the formatted string
124  return str;
125 }
126 
127 
128 /**
129  * @brief Format date
130  * @param[in] date Pointer to a structure representing the date
131  * @param[out] str NULL-terminated string representing the specified date
132  * @return Pointer to the formatted string
133  **/
134 
135 const char_t *formatDate(const DateTime *date, char_t *str)
136 {
137  static char_t buffer[40];
138 
139  //The parameter is optional
140  if(str == NULL)
141  {
142  str = buffer;
143  }
144 
145  //Format date
146  if(date->dayOfWeek)
147  {
148  osSprintf(str, "%s, %s %" PRIu8 ", %" PRIu16 " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8,
149  days[MIN(date->dayOfWeek, 7)], months[MIN(date->month, 12)], date->day,
150  date->year, date->hours, date->minutes, date->seconds);
151  }
152  else
153  {
154  osSprintf(str, "%s %" PRIu8 ", %" PRIu16 " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8,
155  months[MIN(date->month, 12)], date->day, date->year,
156  date->hours, date->minutes, date->seconds);
157  }
158 
159  //Return a pointer to the formatted string
160  return str;
161 }
162 
163 
164 /**
165  * @brief Get current date and time
166  * @param[out] date Pointer to a structure representing the date and time
167  **/
168 
170 {
171  time_t time;
172 
173  //Retrieve current time
175 
176  //Convert Unix timestamp to date
178 }
179 
180 
181 /**
182  * @brief Get current time
183  * @return Unix timestamp
184  **/
185 
186 __weak_func time_t getCurrentUnixTime(void)
187 {
188 #if defined(_WIN32)
189  //Retrieve current time
190  return time(NULL);
191 #else
192  //Not implemented
193  return 0;
194 #endif
195 }
196 
197 
198 /**
199  * @brief Convert Unix timestamp to date
200  * @param[in] t Unix timestamp
201  * @param[out] date Pointer to a structure representing the date and time
202  **/
203 
204 void convertUnixTimeToDate(time_t t, DateTime *date)
205 {
206  uint32_t a;
207  uint32_t b;
208  uint32_t c;
209  uint32_t d;
210  uint32_t e;
211  uint32_t f;
212 
213  //Negative Unix time values are not supported
214  if(t < 1)
215  {
216  t = 0;
217  }
218 
219  //Clear milliseconds
220  date->milliseconds = 0;
221 
222  //Retrieve hours, minutes and seconds
223  date->seconds = t % 60;
224  t /= 60;
225  date->minutes = t % 60;
226  t /= 60;
227  date->hours = t % 24;
228  t /= 24;
229 
230  //Convert Unix time to date
231  a = (uint32_t) ((4 * t + 102032) / 146097 + 15);
232  b = (uint32_t) (t + 2442113 + a - (a / 4));
233  c = (20 * b - 2442) / 7305;
234  d = b - 365 * c - (c / 4);
235  e = d * 1000 / 30601;
236  f = d - e * 30 - e * 601 / 1000;
237 
238  //January and February are counted as months 13 and 14 of the previous year
239  if(e <= 13)
240  {
241  c -= 4716;
242  e -= 1;
243  }
244  else
245  {
246  c -= 4715;
247  e -= 13;
248  }
249 
250  //Retrieve year, month and day
251  date->year = c;
252  date->month = e;
253  date->day = f;
254 
255  //Calculate day of week
256  date->dayOfWeek = computeDayOfWeek(c, e, f);
257 }
258 
259 
260 /**
261  * @brief Convert 64-bit Unix timestamp to date
262  * @param[in] t 64-bit Unix timestamp
263  * @param[out] date Pointer to a structure representing the date and time
264  **/
265 
267 {
268  uint32_t a;
269  uint32_t b;
270  uint32_t c;
271  uint32_t d;
272  uint32_t e;
273  uint32_t f;
274 
275  //Negative Unix time values are not supported
276  if(t < 1)
277  {
278  t = 0;
279  }
280 
281  //Clear milliseconds
282  date->milliseconds = 0;
283 
284  //Retrieve hours, minutes and seconds
285  date->seconds = t % 60;
286  t /= 60;
287  date->minutes = t % 60;
288  t /= 60;
289  date->hours = t % 24;
290  t /= 24;
291 
292  //Convert Unix time to date
293  a = (uint32_t) ((4 * t + 102032) / 146097 + 15);
294  b = (uint32_t) (t + 2442113 + a - (a / 4));
295  c = (20 * b - 2442) / 7305;
296  d = b - 365 * c - (c / 4);
297  e = d * 1000 / 30601;
298  f = d - e * 30 - e * 601 / 1000;
299 
300  //January and February are counted as months 13 and 14 of the previous year
301  if(e <= 13)
302  {
303  c -= 4716;
304  e -= 1;
305  }
306  else
307  {
308  c -= 4715;
309  e -= 13;
310  }
311 
312  //Retrieve year, month and day
313  date->year = c;
314  date->month = e;
315  date->day = f;
316 
317  //Calculate day of week
318  date->dayOfWeek = computeDayOfWeek(c, e, f);
319 }
320 
321 
322 /**
323  * @brief Convert date to Unix timestamp
324  * @param[in] date Pointer to a structure representing the date and time
325  * @return Unix timestamp
326  **/
327 
328 time_t convertDateToUnixTime(const DateTime *date)
329 {
330  uint_t y;
331  uint_t m;
332  uint_t d;
333  time_t t;
334 
335  //Year
336  y = date->year;
337  //Month of year
338  m = date->month;
339  //Day of month
340  d = date->day;
341 
342  //January and February are counted as months 13 and 14 of the previous year
343  if(m <= 2)
344  {
345  m += 12;
346  y -= 1;
347  }
348 
349  //Convert years to days
350  t = (365 * y) + (y / 4) - (y / 100) + (y / 400);
351  //Convert months to days
352  t += (30 * m) + (3 * (m + 1) / 5) + d;
353  //Unix time starts on January 1st, 1970
354  t -= 719561;
355  //Convert days to seconds
356  t *= 86400;
357  //Add hours, minutes and seconds
358  t += (3600 * date->hours) + (60 * date->minutes) + date->seconds;
359 
360  //Return Unix time
361  return t;
362 }
363 
364 
365 /**
366  * @brief Convert date to 64-bit Unix timestamp
367  * @param[in] date Pointer to a structure representing the date and time
368  * @return 64-bit Unix timestamp
369  **/
370 
372 {
373  uint_t y;
374  uint_t m;
375  uint_t d;
376  time64_t t;
377 
378  //Year
379  y = date->year;
380  //Month of year
381  m = date->month;
382  //Day of month
383  d = date->day;
384 
385  //January and February are counted as months 13 and 14 of the previous year
386  if(m <= 2)
387  {
388  m += 12;
389  y -= 1;
390  }
391 
392  //Convert years to days
393  t = (365 * y) + (y / 4) - (y / 100) + (y / 400);
394  //Convert months to days
395  t += (30 * m) + (3 * (m + 1) / 5) + d;
396  //Unix time starts on January 1st, 1970
397  t -= 719561;
398  //Convert days to seconds
399  t *= 86400;
400  //Add hours, minutes and seconds
401  t += (3600 * date->hours) + (60 * date->minutes) + date->seconds;
402 
403  //Return 64-bit Unix time
404  return t;
405 }
406 
407 
408 /**
409  * @brief Compare dates
410  * @param[in] date1 Pointer to the first date
411  * @param[in] date2 Pointer to the second date
412  * @return Comparison result
413  **/
414 
415 int_t compareDateTime(const DateTime *date1, const DateTime *date2)
416 {
417  int_t res;
418 
419  //Perform comparison
420  if(date1->year < date2->year)
421  {
422  res = -1;
423  }
424  else if(date1->year > date2->year)
425  {
426  res = 1;
427  }
428  else if(date1->month < date2->month)
429  {
430  res = -1;
431  }
432  else if(date1->month > date2->month)
433  {
434  res = 1;
435  }
436  else if(date1->day < date2->day)
437  {
438  res = -1;
439  }
440  else if(date1->day > date2->day)
441  {
442  res = 1;
443  }
444  else if(date1->hours < date2->hours)
445  {
446  res = -1;
447  }
448  else if(date1->hours > date2->hours)
449  {
450  res = 1;
451  }
452  else if(date1->minutes < date2->minutes)
453  {
454  res = -1;
455  }
456  else if(date1->minutes > date2->minutes)
457  {
458  res = 1;
459  }
460  else if(date1->seconds < date2->seconds)
461  {
462  res = -1;
463  }
464  else if(date1->seconds > date2->seconds)
465  {
466  res = 1;
467  }
468  else if(date1->milliseconds < date2->milliseconds)
469  {
470  res = -1;
471  }
472  else if(date1->milliseconds > date2->milliseconds)
473  {
474  res = 1;
475  }
476  else
477  {
478  res = 0;
479  }
480 
481  //Return comparison result
482  return res;
483 }
484 
485 
486 /**
487  * @brief Calculate day of week
488  * @param[in] y Year
489  * @param[in] m Month of year (in range 1 to 12)
490  * @param[in] d Day of month (in range 1 to 31)
491  * @return Day of week (in range 1 to 7)
492  **/
493 
494 uint8_t computeDayOfWeek(uint16_t y, uint8_t m, uint8_t d)
495 {
496  uint_t h;
497  uint_t j;
498  uint_t k;
499 
500  //January and February are counted as months 13 and 14 of the previous year
501  if(m <= 2)
502  {
503  m += 12;
504  y -= 1;
505  }
506 
507  //J is the century
508  j = y / 100;
509  //K the year of the century
510  k = y % 100;
511 
512  //Compute H using Zeller's congruence
513  h = d + (26 * (m + 1) / 10) + k + (k / 4) + (5 * j) + (j / 4);
514 
515  //Return the day of the week
516  return ((h + 5) % 7) + 1;
517 }
Date and time management.
uint8_t b
Definition: nbns_common.h:122
uint8_t a
Definition: ndp.h:411
signed int int_t
Definition: compiler_port.h:56
time64_t convertDateToUnixTime64(const DateTime *date)
Convert date to 64-bit Unix timestamp.
Definition: date_time.c:371
time_t convertDateToUnixTime(const DateTime *date)
Convert date to Unix timestamp.
Definition: date_time.c:328
uint16_t year
Definition: date_time.h:55
uint8_t t
Definition: lldp_ext_med.h:212
void convertUnixTimeToDate(time_t t, DateTime *date)
Convert Unix timestamp to date.
Definition: date_time.c:204
uint8_t computeDayOfWeek(uint16_t y, uint8_t m, uint8_t d)
Calculate day of week.
Definition: date_time.c:494
int64_t time64_t
64-bit time representation
Definition: date_time.h:46
const uint8_t res[]
const char_t * formatSystemTime(systime_t time, char_t *str)
Format system time.
Definition: date_time.c:77
uint8_t day
Definition: date_time.h:57
uint8_t h
Definition: ndp.h:302
uint8_t minutes
Definition: date_time.h:60
#define osSprintf(dest,...)
Definition: os_port.h:234
void getCurrentDate(DateTime *date)
Get current date and time.
Definition: date_time.c:169
const char_t * formatDate(const DateTime *date, char_t *str)
Format date.
Definition: date_time.c:135
uint8_t hours
Definition: date_time.h:59
Date and time representation.
Definition: date_time.h:54
#define MIN(a, b)
Definition: os_port.h:63
uint8_t seconds
Definition: date_time.h:61
uint32_t systime_t
System time.
uint8_t month
Definition: date_time.h:56
char char_t
Definition: compiler_port.h:55
uint32_t time
uint8_t m
Definition: ndp.h:304
void convertUnixTimeToDate64(time64_t t, DateTime *date)
Convert 64-bit Unix timestamp to date.
Definition: date_time.c:266
uint16_t milliseconds
Definition: date_time.h:62
uint8_t dayOfWeek
Definition: date_time.h:58
unsigned int uint_t
Definition: compiler_port.h:57
__weak_func time_t getCurrentUnixTime(void)
Get current time.
Definition: date_time.c:186
uint8_t c
Definition: ndp.h:514
int_t compareDateTime(const DateTime *date1, const DateTime *date2)
Compare dates.
Definition: date_time.c:415