What's the time Mr Wolf?

Hi,

This is my first post but I have decades of development behind me (sadly not C++ :confused: )
My project is to display the weather using an ESP32

No worries I thought, I’ll fire off an API call to Darksky sorry Climacell and use the info fired back.
As it happens they have just what I need but the API’s default is to return 96 hours worth of forecast data. Thankfully they have a start and end time so that I can reduce the data sent back to just say 24 hours

To do this I can set the start time to “now” - nice and easy
But then comes the hard bit - I have to provide tomorrow as the end time in ISO8601 format
(YYYY-MM-DDTHH:mm:ssZ)

Thankfully we have sprintf to sort out the formatting but getting tomorrows date reduced me to a sobbing child - Hence the title :frowning:

In the end, I came up with this verbose solution (see below)
On reflection, it just looks like I’ve gone round the houses when there must be a more direct approach
Two questions:

  1. The Serial Monitor reports what seems to be correct - But have I missed something?
  2. Is there a better way of calculating tomorrow’s date

#include <Arduino.h>
#include <Time.h>
#include <TimeLib.h>

void tomorrow_ISO8601(char isodate[30] ){

tmElements_t tim;
time_t tomorrow;

struct tm timeinfo;

if(!getLocalTime(&timeinfo)){
Serial.println(“Failed to obtain time”);
}

byte _month = timeinfo.tm_mon + 1;
int _year = timeinfo.tm_year +1900;

tim.Second = timeinfo.tm_sec;
tim.Hour = timeinfo.tm_hour;
tim.Minute = timeinfo.tm_min;
tim.Day = timeinfo.tm_mday;
tim.Month = _month;
tim.Year = _year - 1970; // offset from 1970;
tomorrow = makeTime(tim); // convert time elements into time_t (seconds)
tomorrow += 86400; //add number of seconds in a day

sprintf(isodate, “%4d-%02d-%02dT%d:%02d:%02d.000Z”, year(tomorrow), month(tomorrow), day(tomorrow),
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
}

Isn't there a function to get the local time as a 'time_t' rather than as 'struct tm'? Then you could skip all of the parts moving fields from 'struct tm' to 'tmElements_t' just so that it can be converted to a 'time_t'.

I'm not convinced that there is a better way - dealing with time is a pain. The only alternative I can see is to do it "by hand", but then you've got to deal with leap years and "30 days hath September...".

I'd stick with your version, that device has plenty of memory.

I see some services offering an API to tell you the time, but a quick google didn't find one that allows an offset.

johnwasser:
Isn't there a function to get the local time as a 'time_t' rather than as 'struct tm'? Then you could skip all of the parts moving fields from 'struct tm' to 'tmElements_t' just so that it can be converted to a 'time_t'.

Hmmm . . . that would be nice :slight_smile:

I'll go take a perusal . . .

wildbill:
I'm not convinced that there is a better way - dealing with time is a pain. The only alternative I can see is to do it "by hand", but then you've got to deal with leap years and "30 days hath September...".

I'd stick with your version, that device has plenty of memory.

I see some services offering an API to tell you the time, but a quick google didn't find one that allows an offset.

Yep - I'm happy syncing up using NTP but it too doesn't offer offset :frowning:
John's suggestion sounds hopeful but I'm not holding my breath

charlesgoodwin:
Hmmm . . . that would be nice :slight_smile:

I'll go take a perusal . . .

Hey - I fund the function now()
This returns the date in seconds.
So my function now looks like this:

void tomorrow_ISO8601(char isodate[30] ){

time_t tomorrow;

tomorrow = now(); // fetch today in seconds
tomorrow += 86400; //add number of seconds in a day

sprintf(isodate, "%4d-%02d-%02dT%d:%02d:%02d.000Z", year(tomorrow), month(tomorrow), day(tomorrow),
hour(tomorrow), minute(tomorrow), second(tomorrow));
}

Of course I've shifted out some code to the NTP sync function which looks like this:

void timeSync(){
//init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
setTime(timeinfo.tm_hour,
timeinfo.tm_min,
timeinfo.tm_sec,
timeinfo.tm_mday,
timeinfo.tm_mon + 1,
timeinfo.tm_year +1900);
printLocalTime();
}

And yes, it's still clunky as I am now maintaining TWO time systems
One for syncing up to the NTP Server using configTime
and the other, setTime for working in seconds for the time.

Is this as good as it gets or does someone know any better?