Time zone issue

I’m using the RTC widget in my project. The time is being synchronised with the Blynk server, formatted by strftime and printed as under:

tm * ts;

void requestTime() {
  Blynk.sendInternal("rtc", "sync");
}

BLYNK_WRITE(InternalPinRTC) {
  long t = param.asLong();
  setTime(t);
  Serial.print("\nUnix time: ");
  Serial.print(t);
  Serial.println();
  rawtime=t;
  char daystr[3]="";
  char timestr[6]="";
  char yearstr[5] = "";
  
  if (IsFirstConnect) 
  {
    FirstConnectTime=t;
    IsFirstConnect=0;
    Serial.print("First Connect: ");
    Serial.print(t);
    Serial.print(" :: ");
    /* Needs <time.h> to be included. Can give out formatted time.*/
    ts = localtime ( &rawtime );
    strftime (time_stamp,80,"%a %I:%M %p %d %b %G %Z.",ts);
    Serial.println(time_stamp);
    firstconnect_ts=time_stamp;
  }
}

The time reported by now() is in sync with the phone clock. The time stamp returns GMT as the time zone while the widget has Asia\Kolkatta as the time zone. By this, the strftime should show IST and not GMT.

All help appreciated.

@mohan_sundaram paste a minimal sketch of a connection to Blynk that just has this issue so we can see exactly which libraries you are using etc.

@Costas it is the same code I sent you 2 days ago for the hostname problem. Please see the serial monitor output for time string print outs.

here it is

#define BLYNK_PRINT Serial

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager
#include <EEPROM.h>
#include <TimeLib.h>
#include <time.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "";
tm * ts;
long FirstConnectTime, rawtime;
int IsFirstConnect;
char time_stamp[80];


// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Linksys-01750";
char pass[] = "**********";

BlynkTimer timer;

void requestTime() {
  Blynk.sendInternal("rtc", "sync");
}

BLYNK_WRITE(InternalPinRTC)
{
  long t = param.asLong();
  setTime(t);
  Serial.print("\nUnix time: ");
  Serial.print(t);
  Serial.println();
  rawtime = t;


  /* Needs <time.h> to be included. Can give out formatted time.*/
  ts = localtime ( &rawtime );
  strftime (time_stamp, 80, "%a %I:%M %p %d %b %G %Z.", ts);
  Serial.println(time_stamp);

}

void setup()
{
  // Debug console
  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 8442);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8442);

  requestTime();
}

void loop()
{
  Blynk.run();

}

@mohan_sundaram I have taken all the irrelevant libraries out of your sketch like EEPROM and WiFiManager etc.

I have left the RTC widget with Calcutta time (GMT + 5.5 hours).

Serial monitor gives me correct time of:

Mon 08:18 PM 19 Feb 2018 GMT.

Paste your Serial Monitor output.

I get the same. The tz should be IST and not GMT.

What’s the difference between IST and GMT + 5.5?
Is it related to DST or is there no difference?

It should say 8.18pm IST. If the strftime arg is %z, it gives the time offset and %Z should give the 3 char equivalent. For India, it is IST. IST = GMT +0530

Ah yes I see.

I guess it’s something to do with all the different versions of time library.

You could do a substitution from GMT to IST before you print to Serial Monitor or Blynk Terminal.

Sure can. I’ve removed tz and formed the print string. But, I know there is a problem still.

Yes but probably not Blynk related.

Could we be sure? The RTC sync call is a Blynk call and not any other. So also is the widget. I suspect the regular time libraries would’ve been resolved of such errors before roll out.

@mohan_sundaram can I ask you to provide the same sketch but without any Blynk code i.e. using a time server and paste Serial Monitor showing IST (without any hacks at your side).

Will try. I’m not sure how well I would do this though.

Indulge me for a while please as I’m thinking aloud here. The blynk.sendinternal returns epoch time. The epoch time is converted to struct tm by localtime and then formatted for print by strftime. So, localtime or breakTime is what generates the tz. We provide the tz in the RTC widget. How does Blynk pass this on to the call so that the appropriate tz is set and the current time calculated?

If we have to set the tz ourselves in the sketch, them Blynk should give us a variable or argument to read from, based on the widget setting. Is my surmise wrong?

Edit added: This whole thing is wrong if the Blynk server returns epoch time adjusted for the timezone set in the widget. This possibly could be the most likely case. There is no other way the correct time can be returned without the timezone explicitly being set. Will check this by comparing the serial output epoch with epoch shown by sites at the same time.

@Costas. Rebooted my board and checked the epoch time on the internet at the same time. There is a difference of about 19,700… Leads me to believe that the number returned by the blynk server on rtc sync is already adjusted for the time zone. This is ok, now that I know it. However, the device should know the timezone too in some form from the blynk server.

Blynk team - any take on this?

Was looking through the downloaded files for Blynk on my system. See a header file called BlynkDateTime.h and in that the following:


    blynk_time_t getUnixOffset() const { return mTime; }

    bool isValid()  const { return mTime < MAX_TIME; }
    operator bool() const { return isValid(); }

    bool operator == (const BlynkTime& t) const { return mTime == t.mTime; }
    bool operator >= (const BlynkTime& t) const { return mTime >= t.mTime; }
    bool operator <= (const BlynkTime& t) const { return mTime <= t.mTime; }
    bool operator >  (const BlynkTime& t) const { return mTime >  t.mTime; }
    bool operator <  (const BlynkTime& t) const { return mTime <  t.mTime; }

private:
    uint32_t mTime;
};

class BlynkDateTime {

public:
    BlynkDateTime() : mTime(0) {}

    BlynkDateTime(const BlynkDateTime& t)
    {
        mTime = t.mTime;
        blynk_gmtime_r(&mTime, &mTm);
    }

There is a definition for getting offset and another call blynk_gmtime_r(&mTime, &mTm);

I’m not C literate. Can some one help me to decide if these can be used in the sketch to get the timezone or the time offset from UTC?

I’ve used the Blynk.sendInternal() call to get the RTC epoch number from the server I’m unable to see the dcoumentation for this call in the docs. It is possible that I’ve not looked well enough. Seems like a call to get some server resident settings. Would like to know what else one can do with this call. I saw this in the advanced RTC sketch and did a copy-paste…

Based on the sketch in question, Blynk.sendInternal("rtc", "sync"); is simply a call that synchronises the RTC widget with the server time and calls this function to get the UI time…

BLYNK_WRITE(InternalPinRTC) {
  long UnixTime = param.asLong();
}

Probably useful in advanced cases where you have a sketch that needs the full UI time instead of real world breakdown of hours, minutes, seconds, etc.

Searching through the Blynk library files shows that this command is only used with the RTC. As per WidgetRTC.h It is an internal command called from the Time Library variable type time_t AKA Unix Time

It is used for… surprize :slight_smile:, internal needs. Right now we use it for setting heartbeat interval and updating info about firmware.

1 Like

Can this be extended and made available to sers? E.g read RTC TZ from server, labels of widgets, server IP etc.