COSA
An Object-Oriented Platform for Arduino Programming
Time.cpp
Go to the documentation of this file.
1 
21 #include "Cosa/Time.hh"
22 
24 {
25  outs << time_t::full_year( t.year ) << '-';
26  if (t.month < 10) outs << '0';
27  outs << t.month << '-';
28  if (t.date < 10) outs << '0';
29  outs << t.date << ' ';
30  if (t.hours < 10) outs << '0';
31  outs << t.hours << ':';
32  if (t.minutes < 10) outs << '0';
33  outs << t.minutes << ':';
34  if (t.seconds < 10) outs << '0';
35  outs << t.seconds;
36  return (outs);
37 }
38 
39 bool
41 {
42  static size_t BUF_MAX = 32;
43  char buf[BUF_MAX];
44  strcpy_P(buf, s);
45  char* sp = &buf[0];
46  uint16_t value = strtoul(sp, &sp, 10);
47 
48  if (UNLIKELY(*sp != '-')) return false;
49  year = value % 100;
50  if (UNLIKELY(full_year() != value)) return false;
51 
52  value = strtoul(sp + 1, &sp, 10);
53  if (UNLIKELY(*sp != '-')) return false;
54  month = value;
55 
56  value = strtoul(sp + 1, &sp, 10);
57  if (UNLIKELY(*sp != ' ')) return false;
58  date = value;
59 
60  value = strtoul(sp + 1, &sp, 10);
61  if (UNLIKELY(*sp != ':')) return false;
62  hours = value;
63 
64  value = strtoul(sp + 1, &sp, 10);
65  if (UNLIKELY(*sp != ':')) return false;
66  minutes = value;
67 
68  value = strtoul(sp + 1, &sp, 10);
69  if (UNLIKELY(*sp != 0)) return false;
70  seconds = value;
71 
72  set_day();
73  return (is_valid());
74 }
75 
77 uint8_t time_t::epoch_offset = 0;
79 uint8_t time_t::pivot_year = 0;
80 
81 const uint8_t time_t::days_in[] __PROGMEM = {
82  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
83 };
84 
85 time_t::time_t(clock_t c, int8_t zone)
86 {
87  c += zone * (int32_t) SECONDS_PER_HOUR;
88  uint16_t dayno = c / SECONDS_PER_DAY;
89  c -= dayno * (uint32_t) SECONDS_PER_DAY;
90  day = weekday_for(dayno);
91 
92  uint16_t y = epoch_year();
93  for (;;) {
94  uint16_t days = days_per(y);
95  if (dayno < days) break;
96  dayno -= days;
97  y++;
98  }
99  bool leap_year = is_leap(y);
100  y -= epoch_year();
101  y += epoch_offset;
102  while (y > 100)
103  y -= 100;
104  year = y;
105 
106  month = 1;
107  for (;;) {
108  uint8_t days = pgm_read_byte(&days_in[month]);
109  if (leap_year && (month == 2)) days++;
110  if (dayno < days) break;
111  dayno -= days;
112  month++;
113  }
114  date = dayno + 1;
115 
116  hours = c / SECONDS_PER_HOUR;
117 
118  uint16_t c_ms;
119  if (hours < 18) // save 16uS
120  c_ms = (uint16_t) c - (hours * (uint16_t) SECONDS_PER_HOUR);
121  else
122  c_ms = c - (hours * (uint32_t) SECONDS_PER_HOUR);
123  minutes = c_ms / SECONDS_PER_MINUTE;
124  seconds = c_ms - (minutes * SECONDS_PER_MINUTE);
125 }
126 
127 time_t::operator clock_t() const
128 {
129  clock_t c = days() * SECONDS_PER_DAY;
130  if (hours < 18)
131  c += hours * (uint16_t) SECONDS_PER_HOUR;
132  else
133  c += hours * (uint32_t) SECONDS_PER_HOUR;
134  c += minutes * (uint16_t) SECONDS_PER_MINUTE;
135  c += seconds;
136 
137  return (c);
138 }
139 
140 uint16_t time_t::days() const
141 {
142  uint16_t day_count = day_of_year();
143 
144  uint16_t y = full_year();
145  while (y-- > epoch_year())
146  day_count += days_per(y);
147 
148  return (day_count);
149 }
150 
151 uint16_t time_t::day_of_year() const
152 {
153  uint16_t dayno = date - 1;
154  bool leap_year = is_leap();
155 
156  for (uint8_t m = 1; m < month; m++) {
157  dayno += pgm_read_byte(&days_in[m]);
158  if (leap_year && (m == 2)) dayno++;
159  }
160 
161  return (dayno);
162 }
163 
165 {
166  // Figure out when we were compiled and use the year for a really
167  // fast epoch_year. Format "MMM DD YYYY"
168  const char* compile_date = (const char *) PSTR(__DATE__);
169  uint16_t compile_year = 0;
170  for (uint8_t i = 7; i < 11; i++)
171  compile_year = compile_year*10 + (pgm_read_byte(&compile_date[i]) - '0');
172 
173  // Temporarily set a Y2K epoch so we can figure out the day for
174  // January 1 of this year
177  time_t this_year(0);
178  this_year.year = compile_year % 100;
179  this_year.set_day();
180  uint8_t compile_weekday = this_year.day;
181 
182  time_t::epoch_year(compile_year);
183  time_t::epoch_weekday = compile_weekday;
184  time_t::pivot_year = this_year.year;
185 }
static const uint8_t days_in[]
Definition: Time.hh:304
const uint16_t Y2K_EPOCH_YEAR
Definition: Time.hh:48
uint8_t minutes
00-59 Minutes.
Definition: Time.hh:104
static uint16_t epoch_year()
Definition: Time.hh:273
static uint8_t pivot_year
Definition: Time.hh:285
uint8_t day
01-07 Day.
Definition: Time.hh:106
bool parse(str_P s)
Definition: Time.cpp:40
#define PSTR(s)
Definition: Types.h:202
uint16_t days() const
Definition: Time.cpp:140
bool is_leap() const
Definition: Time.hh:199
uint32_t clock_t
Definition: Time.hh:55
uint8_t month
01-12 Month.
Definition: Time.hh:108
time_t()
Definition: Time.hh:134
static uint16_t days_per(uint16_t year)
Definition: Time.hh:221
const uint8_t Y2K_EPOCH_WEEKDAY
Definition: Time.hh:49
static uint8_t epoch_weekday
Definition: Time.hh:278
const class prog_str * str_P
Definition: Types.h:187
const uint32_t SECONDS_PER_DAY
Definition: Time.hh:57
const uint8_t SECONDS_PER_MINUTE
Definition: Time.hh:59
void set_day()
Definition: Time.hh:152
uint8_t year
00-99 Year.
Definition: Time.hh:109
char * strcpy_P(char *s1, str_P s2)
Definition: Types.h:236
uint8_t seconds
00-59 Seconds.
Definition: Time.hh:103
Definition: Time.hh:102
bool is_valid() const
Definition: Time.hh:240
static void use_fastest_epoch()
Definition: Time.cpp:164
const uint8_t time_t::days_in[] __PROGMEM
Definition: Time.cpp:81
uint8_t hours
00-23 Hours.
Definition: Time.hh:105
static uint8_t epoch_offset
Definition: Time.hh:308
uint8_t date
01-31 Date.
Definition: Time.hh:107
uint16_t full_year() const
Definition: Time.hh:173
IOStream & operator<<(IOStream &outs, const time_t &t)
Definition: Time.cpp:23
uint16_t day_of_year() const
Definition: Time.cpp:151
#define UNLIKELY(x)
Definition: Types.h:153
static uint8_t weekday_for(uint16_t dayno)
Definition: Time.hh:231
static uint16_t s_epoch_year
Definition: Time.hh:307
const uint16_t SECONDS_PER_HOUR
Definition: Time.hh:58