Author Topic: Arduino, Converting Epoch to Year, Month, Day, Weekday  (Read 30318 times)

0 Members and 1 Guest are viewing this topic.

Offline kolbepTopic starter

  • Frequent Contributor
  • **
  • Posts: 598
  • Country: za
    • ShoutingElectronics.com
Arduino, Converting Epoch to Year, Month, Day, Weekday
« on: August 29, 2016, 06:02:17 pm »
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 anyway
2) Removed DHT11 Sensor - Not Enough Resolution (For my liking)
3) Replaced with DS18B20 Temperature Sensor
4) 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: [Select]
    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 get
year
month
day
dayofweek


Much appreciated for your help
====================================
www.ShoutingElectronics.com Don't just talk about Electronics, SHOUT ABOUT IT! Electronics Blog Site and Youtube Channel
 

Offline electr_peter

  • Supporter
  • ****
  • Posts: 1301
  • Country: lt
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #1 on: August 29, 2016, 07:11:38 pm »
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.
 

Offline oPossum

  • Super Contributor
  • ***
  • Posts: 1415
  • Country: us
  • Very dangerous - may attack at any time
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #2 on: August 29, 2016, 08:52:32 pm »
Code: [Select]
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, seconds
    ldiv_t d = ldiv(t, 60);                             // Seconds
    rtc.sec = dec2bcd(d.rem);                           //
    d = ldiv(d.quot, 60);                               // Minutes
    rtc.min = dec2bcd(d.rem);                           //
    d = ldiv(d.quot, 24);                               // Hours
    rtc.hour = dec2bcd(d.rem);                          //
    rtc.dow = ((d.quot + 4) % 7) + 1;                   // Day of week
    d = ldiv(d.quot, 365);                              // Day of year
    int doy = d.rem;                                    //
    unsigned yr = d.quot + 1970;                        // Year
                                                        //
                                                        // - Adjust day of year for leap years
    unsigned ly;                                        // Leap year
    for(ly = 1972; ly < yr; ly += 4) {                  // Adjust year and day of year for leap years
        if(!(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 underflow
    rtc.year = dec2bcd(yr - 2000);                      //
                                                        //
                                                        // - Find month and day of month from day of year
    static uint8_t const dm[2][12] = {                  // 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 month
    rtc.month = 0;                                      // Init month
    ly = (yr == ly) ? 1 : 0;                            // Make leap year index 0 = not a leap year, 1 = is a leap year
    while(day > dm[ly][rtc.month]) day -= dm[ly][rtc.month++]; // Calculate month and day of month
                                                        //
    rtc.doy = doy + 1;                                  // - Make date ones based
    rtc.day = dec2bcd(day + 1);                         //
    rtc.month = dec2bcd(rtc.month + 1);                 //
    rtc.ampm = 0;                                       //
}                                                       //
                                                        //
« Last Edit: August 29, 2016, 08:58:25 pm by oPossum »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #3 on: August 29, 2016, 08:53:59 pm »
Look into your compiler manual and there is likely a set of unix-ish functions that do that.

================================
https://dannyelectronics.wordpress.com/
 

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2850
  • Country: se
  • Country: Broken Britain
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #4 on: August 29, 2016, 09:26:17 pm »
How are you going to allow for the leap seconds that have occasionally been added to Earth time?
.  That took much longer than I thought it would.
 

Offline djacobow

  • Super Contributor
  • ***
  • Posts: 1151
  • Country: us
  • takin' it apart since the 70's
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #5 on: August 29, 2016, 10:00:45 pm »
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.
 

Offline kolbepTopic starter

  • Frequent Contributor
  • **
  • Posts: 598
  • Country: za
    • ShoutingElectronics.com
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #6 on: August 30, 2016, 04:41:45 am »
THanks.
Turns out there is a TimeLib library that does that nicely:
Code: [Select]
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.
====================================
www.ShoutingElectronics.com Don't just talk about Electronics, SHOUT ABOUT IT! Electronics Blog Site and Youtube Channel
 

Offline kolbepTopic starter

  • Frequent Contributor
  • **
  • Posts: 598
  • Country: za
    • ShoutingElectronics.com
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #7 on: August 30, 2016, 04:48:03 am »
And it works!!!!
Code: [Select]
   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 Output
Code: [Select]
[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 1.3.0
Attempting to connect to WPA SSID: [WiFiEsp] Connected to mypnet
You're connected to the network
SSID: mypnet
IP Address: 192.168.1.22
Signal strength (RSSI):-562 dBm

Device 0 Address: 28D8B372070000AF
.
-127.00
RTC TIME 6:45:45 NTPTime 3 2016 8 30 6:45:45
>>> 1st Run - Synching RTC
6:46:45, .
-127.00
RTC TIME 6:46:46 NTPTime 3 2016 8 30 6:46:46
====================================
www.ShoutingElectronics.com Don't just talk about Electronics, SHOUT ABOUT IT! Electronics Blog Site and Youtube Channel
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9925
  • Country: nz
Re: Arduino, Converting Epoch to Year, Month, Day, Weekday
« Reply #8 on: August 30, 2016, 07:35:17 am »
Now you just need daylight savings and UTC+local timezones
Greek letter 'Psi' (not Pounds per Square Inch)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf