Arduino, Converting Epoch to Year, Month, Day, Weekday - Page 1
Forum section: electronics / general

author: kolbep
author_rank: Frequent Contributor
timestamp: August 29, 2016, 06:02:17 pm
content: Hi All.I am busy designing a new controller for my big digit clock.Changes to the design :1) Removed IR Receiver - Don't Use a Remote anyway2) Removed DHT11 Sensor - Not Enough Resolution (For my liking)3) Replaced with DS18B20 Temperature Sensor4) Removed DS1307 RTC (Was running fast about 2 minutes a month (or 4 seconds per day)5) Replaced with DS3231 RTC (So far has not drifted at all)6) Added ESP8266 Wifi Module to grab time from a NTP server (Just the basic Epoch, not all the fancy calculations to get it accurate to the millisecond).When starting up (and maybe daily or weekly) the Time that is grabbed from the NTP server will be used to set the DS3231, to keep it accurate (to the second, I am not too fussy)Now, I want to have automatically switch to a countdown,i.e. If it is 10:00am on a SUNDAY, it must start a 30 minute countdown to zero.The thing is, the code that I have copied only extracts Hours, Minutes, and Seconds from the NTP Servers Epoch Time.How could I modify this code to give me Year, Month, Day, and Day of Week as well (I would like all this, in case I want to have it display the date, and it is also a handy piece of code to keep for other projects.Here is the current code :Code:epoch=epoch+7200 ; //ADD 2 Hours (For GMT+2)// print the hour, minute and second:int hr=(epoch % 86400L) / 3600;int min=(epoch % 3600) / 60;int sec=(epoch % 60);I just need to know what to add to getyearmonthdaydayofweekMuch appreciated for your help

author: electr_peter
author_rank: Unknown
timestamp: August 29, 2016, 07:11:38 pm
content: To my knowledge (and knowledge of programmers I know of), it is relatively difficult to create function that extract year/month/day/weekday/week information from simple time and date (because of leap days and similar). I would use precoded time related functions to relieve this hassle, save time and be sure to have something working properly.In your case - do you know a library for MCU which does this? If not, I would suggest to get additional info from server about year/month/weekday/etc. in addition to simple date and time.

author: oPossum
author_rank: Super Contributor
timestamp: August 29, 2016, 08:52:32 pm
content: Code:struct RTC {uint8_t sec;uint8_t min;uint8_t hour;uint8_t dow;uint8_t day;uint8_t month;uint8_t year;uint8_t config;uint16_t doy; // not BCD!};tatic uint8_t dec2bcd(uint8_t x) //{ //uint8_t n = 0; //while(x > 9) x -= 10, n += 0x10; //n += x; //return n; //} ////void ntp_to_rtc(uint32_t t, RTC &rtc) //{ //t -= (2208988800UL); // Convert to common time_t epoch (Jan 1 1970)t += (-5L * 60 * 60); // Adjust for time zone//// - Convert seconds to year, day of year, day of week, hours, minutes, secondsldiv_t d = ldiv(t, 60); // Secondsrtc.sec = dec2bcd(d.rem); //d = ldiv(d.quot, 60); // Minutesrtc.min = dec2bcd(d.rem); //d = ldiv(d.quot, 24); // Hoursrtc.hour = dec2bcd(d.rem); //rtc.dow = ((d.quot + 4) % 7) + 1; // Day of weekd = ldiv(d.quot, 365); // Day of yearint doy = d.rem; //unsigned yr = d.quot + 1970; // Year//// - Adjust day of year for leap yearsunsigned ly; // Leap yearfor(ly = 1972; ly < yr; ly += 4) { // Adjust year and day of year for leap yearsif(!(ly % 100) && (ly % 400)) continue; // Skip years that are divisible by 100 and not by 400--doy; //} //if(doy < 0) doy += 365, ++yr; // Handle day of year underflowrtc.year = dec2bcd(yr - 2000); ////// - Find month and day of month from day of yearstatic uint8_t const dm = { // Days in each month{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, // Not a leap year{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} // Leap year}; //int day = doy; // Init day of monthrtc.month = 0; // Init monthly = (yr == ly) ? 1 : 0; // Make leap year index 0 = not a leap year, 1 = is a leap yearwhile(day > dm[rtc.month]) day -= dm[rtc.month++]; // Calculate month and day of month//rtc.doy = doy + 1; // - Make date ones basedrtc.day = dec2bcd(day + 1); //rtc.month = dec2bcd(rtc.month + 1); //rtc.ampm = 0; //} ////

author: dannyf
author_rank: Super Contributor
timestamp: August 29, 2016, 08:53:59 pm
content: Look into your compiler manual and there is likely a set of unix-ish functions that do that.

author: StillTrying
author_rank: Super Contributor
timestamp: August 29, 2016, 09:26:17 pm
content: How are you going to allow for the leap seconds that have occasionally been added to Earth time?

author: djacobow
author_rank: Super Contributor
timestamp: August 29, 2016, 10:00:45 pm
content: As others are hinting, if you try to work out these functions yourself, you have a near 100% chance of getting them wrong. It's just really hard to do time right, and winging it is a recipe for heartache.If your compiler setup lacks a libc with these functions (unlikely these days), the good news is that the functions to convert between "struct tm" and "time_t" do not have any dependencies, so if you google for the source of glibc or any other libc that has gmtime_r, localtime_r, mktime you will find nice self-contained implementations that you should be able to compile, perhaps after defining time_t and struct tm if you don't already have headers with them.A minor / not so minor annoyance, of course, is that RTCs store information in a format that requires massaging to map to/from a struct tm. Personally, I've become a fan of the clock chips like DS1374 that just store a simple 32b counter, incremented every second. Just cuts the bullshit out as I'll be dealing with epoch time anyway.

author: kolbep
author_rank: Frequent Contributor
timestamp: August 30, 2016, 04:41:45 am
content: THanks.Turns out there is a TimeLib library that does that nicely:Code:hour(t);minute(t);second(t);day(t);month(t);year(t);Convert a time_t number to a single time or data field. These can be simpler to use than breakTime() and a 7-field TimeElements variable.There is a dayofweek buried in it somewhere.

author: kolbep
author_rank: Frequent Contributor
timestamp: August 30, 2016, 04:48:03 am
content: And it works!!!!Code:Serial.print(weekday(epoch));Serial.print(" ");Serial.print(year(epoch));Serial.print(" ");Serial.print(month(epoch));Serial.print(" ");Serial.print(day(epoch));Serial.print(" ");Serial.print(hr);Serial.print(F(":"));Serial.print(min);Serial.print(F(":"));Serial.print(sec);Serial.println(F(" "));And My OutputCode: Initializing ESP module Initilization successful - 1.3.0Attempting to connect to WPA SSID:  Connected to mypnetYou're connected to the networkSSID: mypnetIP Address: 192.168.1.22Signal strength (RSSI):-562 dBmDevice 0 Address: 28D8B372070000AF.-127.00RTC TIME 6:45:45 NTPTime 3 2016 8 30 6:45:45>>> 1st Run - Synching RTC6:46:45, .-127.00RTC TIME 6:46:46 NTPTime 3 2016 8 30 6:46:46

author: Psi
author_rank: Super Contributor
timestamp: August 30, 2016, 07:35:17 am
content: Now you just need daylight savings and UTC+local timezones