// Copyright (C) 2014-2017, SlashDevin // // This file is part of NeoGPS // // NeoGPS is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // NeoGPS is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with NeoGPS. If not, see . #include "NeoTime.h" // For strtoul declaration #include #include Print & operator<<( Print& outs, const NeoGPS::time_t& t ) { outs.print( t.full_year( t.year ) ); outs.write( '-' ); if (t.month < 10) outs.write( '0' ); outs.print( t.month ); outs.write( '-' ); if (t.date < 10) outs.write( '0' ); outs.print( t.date ); outs.write( ' ' ); if (t.hours < 10) outs.write( '0' ); outs.print( t.hours ); outs.write( ':' ); if (t.minutes < 10) outs.write( '0' ); outs.print( t.minutes ); outs.write( ':' ); if (t.seconds < 10) outs.write( '0' ); outs.print( t.seconds ); return outs; } using NeoGPS::time_t; bool time_t::parse(str_P s) { static size_t BUF_MAX = 32; char buf[BUF_MAX]; strcpy_P(buf, s); char* sp = &buf[0]; uint16_t value = strtoul(sp, &sp, 10); if (*sp != '-') return false; year = value % 100; if (full_year() != value) return false; value = strtoul(sp + 1, &sp, 10); if (*sp != '-') return false; month = value; value = strtoul(sp + 1, &sp, 10); if (*sp != ' ') return false; date = value; value = strtoul(sp + 1, &sp, 10); if (*sp != ':') return false; hours = value; value = strtoul(sp + 1, &sp, 10); if (*sp != ':') return false; minutes = value; value = strtoul(sp + 1, &sp, 10); if (*sp != 0) return false; seconds = value; return (is_valid()); } #ifdef TIME_EPOCH_MODIFIABLE uint16_t time_t::s_epoch_year = Y2K_EPOCH_YEAR; uint8_t time_t::s_epoch_offset = 0; uint8_t time_t::s_epoch_weekday = Y2K_EPOCH_WEEKDAY; uint8_t time_t::s_pivot_year = 0; #endif const uint8_t time_t::days_in[] __PROGMEM = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; time_t::time_t(clock_t c) { uint16_t dayno = c / SECONDS_PER_DAY; c -= dayno * (uint32_t) SECONDS_PER_DAY; day = weekday_for(dayno); uint16_t y = epoch_year(); for (;;) { uint16_t days = days_per( y ); if (dayno < days) break; dayno -= days; y++; } bool leap_year = is_leap(y); y -= epoch_year(); y += epoch_offset(); while (y > 100) y -= 100; year = y; month = 1; for (;;) { uint8_t days = pgm_read_byte(&days_in[month]); if (leap_year && (month == 2)) days++; if (dayno < days) break; dayno -= days; month++; } date = dayno + 1; hours = c / SECONDS_PER_HOUR; uint16_t c_ms; if (hours < 18) // save 16uS c_ms = (uint16_t) c - (hours * (uint16_t) SECONDS_PER_HOUR); else c_ms = c - (hours * (uint32_t) SECONDS_PER_HOUR); minutes = c_ms / SECONDS_PER_MINUTE; seconds = c_ms - (minutes * SECONDS_PER_MINUTE); } void time_t::init() { seconds = hours = minutes = 0; date = 1; month = 1; year = epoch_year() % 100; day = epoch_weekday(); } time_t::operator clock_t() const { clock_t c = days() * SECONDS_PER_DAY; if (hours < 18) c += hours * (uint16_t) SECONDS_PER_HOUR; else c += hours * (uint32_t) SECONDS_PER_HOUR; c += minutes * (uint16_t) SECONDS_PER_MINUTE; c += seconds; return (c); } uint16_t time_t::days() const { uint16_t day_count = day_of_year(); uint16_t y = full_year(); while (y-- > epoch_year()) day_count += days_per(y); return (day_count); } uint16_t time_t::day_of_year() const { uint16_t dayno = date - 1; bool leap_year = is_leap(); for (uint8_t m = 1; m < month; m++) { dayno += pgm_read_byte(&days_in[m]); if (leap_year && (m == 2)) dayno++; } return (dayno); } #ifdef TIME_EPOCH_MODIFIABLE void time_t::use_fastest_epoch() { // Figure out when we were compiled and use the year for a really // fast epoch_year. Format "MMM DD YYYY" const char* compile_date = (const char *) PSTR(__DATE__); uint16_t compile_year = 0; for (uint8_t i = 7; i < 11; i++) compile_year = compile_year*10 + (pgm_read_byte(&compile_date[i]) - '0'); // Temporarily set a Y2K epoch so we can figure out the day for // January 1 of this year epoch_year ( Y2K_EPOCH_YEAR ); epoch_weekday ( Y2K_EPOCH_WEEKDAY ); time_t this_year(0); this_year.year = compile_year % 100; this_year.set_day(); uint8_t compile_weekday = this_year.day; epoch_year ( compile_year ); epoch_weekday( compile_weekday ); pivot_year ( this_year.year ); } #endif