dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
timeutils.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
28 
29 #include "timeutils.h"
30 
31 /* Test for leap year. Nonzero if YEAR is a leap year (every 4 years,
32  except every 100th isn't, and every 400th is). */
33 # define __isleap(year) \
34  ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
35 
36 /* How many days come before each month (0-12). */
37 static const uint16_t __mon_yday[2][13] = {
38  /* Normal years. */
39  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
40  /* Leap years. */
41  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
42 };
43 
44 #define SECS_PER_HOUR (60 * 60)
45 #define SECS_PER_DAY (SECS_PER_HOUR * 24)
46 
51 void date_from_timestamp(uint32_t timestamp, DateTimeT *date_time)
52 {
53  uint16_t y;
54  int16_t days;
55  uint32_t rem;
56 
57  days = timestamp / SECS_PER_DAY;
58  rem = timestamp % SECS_PER_DAY;
59 
60  date_time->hour = rem / SECS_PER_HOUR;
61  rem %= SECS_PER_HOUR;
62  date_time->min = rem / 60;
63  date_time->sec = rem % 60;
64  /* January 1, 1970 was a Thursday. */
65  date_time->wday = (4 + days) % 7;
66  y = 1970;
67 
68 #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
69 #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
70 
71  while (days < 0 || days >= (__isleap (y) ? 366 : 365))
72  {
73  /* Guess a corrected year, assuming 365 days per year. */
74  uint16_t yg = y + days / 365 - (days % 365 < 0);
75 
76  /* Adjust DAYS and Y to match the guessed year. */
77  days -= ((yg - y) * 365
78  + LEAPS_THRU_END_OF (yg - 1)
79  - LEAPS_THRU_END_OF (y - 1));
80  y = yg;
81  }
82  date_time->year = y - 1900;
83  if (date_time->year != y - 1900)
84  {
85  /* The year cannot be represented due to overflow. */
86  return;
87  }
88  const uint16_t *ip = __mon_yday[__isleap(y)];
89  for (y = 11; days < (uint16_t)ip[y]; --y){
90  continue;
91  }
92  days -= ip[y];
93  date_time->mon = y;
94  date_time->mday = days + 1;
95 }
#define SECS_PER_HOUR
Definition: timeutils.c:44
#define SECS_PER_DAY
Definition: timeutils.c:45
void date_from_timestamp(uint32_t timestamp, DateTimeT *date_time)
Definition: timeutils.c:51
#define __isleap(year)
Definition: timeutils.c:33
#define LEAPS_THRU_END_OF(y)
static const uint16_t __mon_yday[2][13]
Definition: timeutils.c:37
Time conversion functions.