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-2019 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 1.9.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 str parameter is optional
98  if(!str)
99  str = buffer;
100 
101  //Format system time
102  if(hours > 0)
103  {
104  sprintf(str, "%" PRIu16 "h %02" PRIu8 "min %02" PRIu8 "s %03" PRIu16 "ms",
105  hours, minutes, seconds, milliseconds);
106  }
107  else if(minutes > 0)
108  {
109  sprintf(str, "%" PRIu8 "min %02" PRIu8 "s %03" PRIu16 "ms",
110  minutes, seconds, milliseconds);
111  }
112  else if(seconds > 0)
113  {
114  sprintf(str, "%" PRIu8 "s %03" PRIu16 "ms", seconds, milliseconds);
115  }
116  else
117  {
118  sprintf(str, "%" PRIu16 "ms", milliseconds);
119  }
120 
121  //Return a pointer to the formatted string
122  return str;
123 }
124 
125 
126 /**
127  * @brief Format date
128  * @param[in] date Pointer to a structure representing the date
129  * @param[out] str NULL-terminated string representing the specified date
130  * @return Pointer to the formatted string
131  **/
132 
133 const char_t *formatDate(const DateTime *date, char_t *str)
134 {
135  static char_t buffer[40];
136 
137  //The str parameter is optional
138  if(!str)
139  str = buffer;
140 
141  //Format date
142  if(date->dayOfWeek)
143  {
144  sprintf(str, "%s, %s %" PRIu8 ", %" PRIu16 " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8,
145  days[MIN(date->dayOfWeek, 7)], months[MIN(date->month, 12)], date->day,
146  date->year, date->hours, date->minutes, date->seconds);
147  }
148  else
149  {
150  sprintf(str, "%s %" PRIu8 ", %" PRIu16 " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8,
151  months[MIN(date->month, 12)], date->day, date->year,
152  date->hours, date->minutes, date->seconds);
153  }
154 
155  //Return a pointer to the formatted string
156  return str;
157 }
158 
159 
160 /**
161  * @brief Get current date and time
162  * @param[out] date Pointer to a structure representing the date and time
163  **/
164 
166 {
167  //Retrieve current time
168  time_t time = getCurrentUnixTime();
169 
170  //Convert Unix timestamp to date
172 }
173 
174 
175 /**
176  * @brief Get current time
177  * @return Unix timestamp
178  **/
179 
180 time_t getCurrentUnixTime(void)
181 {
182 #if defined(_WIN32)
183  //Retrieve current time
184  return time(NULL);
185 #else
186  //Not implemented
187  return 0;
188 #endif
189 }
190 
191 
192 /**
193  * @brief Convert Unix timestamp to date
194  * @param[in] t Unix timestamp
195  * @param[out] date Pointer to a structure representing the date and time
196  **/
197 
198 void convertUnixTimeToDate(time_t t, DateTime *date)
199 {
200  uint32_t a;
201  uint32_t b;
202  uint32_t c;
203  uint32_t d;
204  uint32_t e;
205  uint32_t f;
206 
207  //Negative Unix time values are not supported
208  if(t < 1)
209  t = 0;
210 
211  //Clear milliseconds
212  date->milliseconds = 0;
213 
214  //Retrieve hours, minutes and seconds
215  date->seconds = t % 60;
216  t /= 60;
217  date->minutes = t % 60;
218  t /= 60;
219  date->hours = t % 24;
220  t /= 24;
221 
222  //Convert Unix time to date
223  a = (uint32_t) ((4 * t + 102032) / 146097 + 15);
224  b = (uint32_t) (t + 2442113 + a - (a / 4));
225  c = (20 * b - 2442) / 7305;
226  d = b - 365 * c - (c / 4);
227  e = d * 1000 / 30601;
228  f = d - e * 30 - e * 601 / 1000;
229 
230  //January and February are counted as months 13 and 14 of the previous year
231  if(e <= 13)
232  {
233  c -= 4716;
234  e -= 1;
235  }
236  else
237  {
238  c -= 4715;
239  e -= 13;
240  }
241 
242  //Retrieve year, month and day
243  date->year = c;
244  date->month = e;
245  date->day = f;
246 
247  //Calculate day of week
248  date->dayOfWeek = computeDayOfWeek(c, e, f);
249 }
250 
251 
252 /**
253  * @brief Convert date to Unix timestamp
254  * @param[in] date Pointer to a structure representing the date and time
255  * @return Unix timestamp
256  **/
257 
258 time_t convertDateToUnixTime(const DateTime *date)
259 {
260  uint_t y;
261  uint_t m;
262  uint_t d;
263  uint32_t t;
264 
265  //Year
266  y = date->year;
267  //Month of year
268  m = date->month;
269  //Day of month
270  d = date->day;
271 
272  //January and February are counted as months 13 and 14 of the previous year
273  if(m <= 2)
274  {
275  m += 12;
276  y -= 1;
277  }
278 
279  //Convert years to days
280  t = (365 * y) + (y / 4) - (y / 100) + (y / 400);
281  //Convert months to days
282  t += (30 * m) + (3 * (m + 1) / 5) + d;
283  //Unix time starts on January 1st, 1970
284  t -= 719561;
285  //Convert days to seconds
286  t *= 86400;
287  //Add hours, minutes and seconds
288  t += (3600 * date->hours) + (60 * date->minutes) + date->seconds;
289 
290  //Return Unix time
291  return t;
292 }
293 
294 
295 /**
296  * @brief Compare dates
297  * @param[in] date1 Pointer to the first date
298  * @param[in] date2 Pointer to the second date
299  * @return Comparison result
300  **/
301 
302 int_t compareDateTime(const DateTime *date1, const DateTime *date2)
303 {
304  int_t res;
305 
306  //Perform comparison
307  if(date1->year < date2->year)
308  res = -1;
309  else if(date1->year > date2->year)
310  res = 1;
311  else if(date1->month < date2->month)
312  res = -1;
313  else if(date1->month > date2->month)
314  res = 1;
315  else if(date1->day < date2->day)
316  res = -1;
317  else if(date1->day > date2->day)
318  res = 1;
319  else if(date1->hours < date2->hours)
320  res = -1;
321  else if(date1->hours > date2->hours)
322  res = 1;
323  else if(date1->minutes < date2->minutes)
324  res = -1;
325  else if(date1->minutes > date2->minutes)
326  res = 1;
327  else if(date1->seconds < date2->seconds)
328  res = -1;
329  else if(date1->seconds > date2->seconds)
330  res = 1;
331  else if(date1->milliseconds < date2->milliseconds)
332  res = -1;
333  else if(date1->milliseconds > date2->milliseconds)
334  res = 1;
335  else
336  res = 0;
337 
338  //Return comparison result
339  return res;
340 }
341 
342 
343 /**
344  * @brief Calculate day of week
345  * @param[in] y Year
346  * @param[in] m Month of year (in range 1 to 12)
347  * @param[in] d Day of month (in range 1 to 31)
348  * @return Day of week (in range 1 to 7)
349  **/
350 
351 uint8_t computeDayOfWeek(uint16_t y, uint8_t m, uint8_t d)
352 {
353  uint_t h;
354  uint_t j;
355  uint_t k;
356 
357  //January and February are counted as months 13 and 14 of the previous year
358  if(m <= 2)
359  {
360  m += 12;
361  y -= 1;
362  }
363 
364  //J is the century
365  j = y / 100;
366  //K the year of the century
367  k = y % 100;
368 
369  //Compute H using Zeller's congruence
370  h = d + (26 * (m + 1) / 10) + k + (k / 4) + (5 * j) + (j / 4);
371 
372  //Return the day of the week
373  return ((h + 5) % 7) + 1;
374 }
uint32_t systime_t
Definition: compiler_port.h:46
uint8_t computeDayOfWeek(uint16_t y, uint8_t m, uint8_t d)
Calculate day of week.
Definition: date_time.c:351
char char_t
Definition: compiler_port.h:43
uint16_t year
Definition: date_time.h:48
uint8_t c
Definition: ndp.h:513
uint32_t time
uint32_t seconds
Definition: ntp_common.h:133
int_t compareDateTime(const DateTime *date1, const DateTime *date2)
Compare dates.
Definition: date_time.c:302
uint8_t minutes
Definition: date_time.h:53
uint8_t t
Definition: llmnr_common.h:81
void getCurrentDate(DateTime *date)
Get current date and time.
Definition: date_time.c:165
uint8_t m
Definition: ndp.h:302
uint8_t a
Definition: ndp.h:410
uint8_t day
Definition: date_time.h:50
const char_t * formatSystemTime(systime_t time, char_t *str)
Format system time.
Definition: date_time.c:77
time_t convertDateToUnixTime(const DateTime *date)
Convert date to Unix timestamp.
Definition: date_time.c:258
signed int int_t
Definition: compiler_port.h:44
uint8_t month
Definition: date_time.h:49
void convertUnixTimeToDate(time_t t, DateTime *date)
Convert Unix timestamp to date.
Definition: date_time.c:198
Date and time management.
uint8_t seconds
Definition: date_time.h:54
#define MIN(a, b)
Definition: os_port.h:62
Date and time representation.
Definition: date_time.h:46
time_t getCurrentUnixTime(void)
Get current time.
Definition: date_time.c:180
uint8_t hours
Definition: date_time.h:52
unsigned int uint_t
Definition: compiler_port.h:45
const uint8_t res[]
uint8_t dayOfWeek
Definition: date_time.h:51
uint16_t milliseconds
Definition: date_time.h:55
uint8_t h
Definition: ndp.h:300
uint8_t b[6]
Definition: dtls_misc.h:132
const char_t * formatDate(const DateTime *date, char_t *str)
Format date.
Definition: date_time.c:133