Date/Time UTC to local time zone conversion

Is there a utility or library that could shift a UTC date/time string like "24/11/10,16:55:41" to a time zone? Like -6, +2, etc.. I'm using the time from a GSM module, derived as "24/11/10,16:55:41-20". The -20 being the UTC offset in 1/4 hours, based on my physical location.

How it's best done depends on which Arduino Board / Processor you're using. And, if you're using any existing time libraries. You haven't told us any of those things. Also, where is this string coming from in the first place?

I use the Arduino Time library (TimeLib.h), and add or subtract the appropriate number of seconds from the unix time.

Example:

//time library demo
#include "TimeLib.h"

tmElements_t te;  //Time elements structure
time_t unixTime; // a time stamp

void setup() {
  Serial.begin(9600);

  // set internal clock time and date. Alternatives 
  // setTime(hr,min,sec,day,mnth,yr);
  te.Second = 0;
  te.Hour = 23; //11 pm
  te.Minute = 0;
  te.Day = 6;
  te.Month = 11;
  te.Year = 2020 - 1970;
  unixTime =  makeTime(te); //Y2K, in seconds = 946684800UL
  Serial.print("unixTime = ");
  Serial.println(unixTime);
  setTime(unixTime); //set the current time to the above entered
  Serial.print("now() = ");
  Serial.println(now());
  // print as date_time
  print_date_time();
  // add
  unixTime += 3600UL; //adjust for DST in spring
  setTime(unixTime);
  Serial.println("After adding DST offset");
  Serial.print("now() = ");
  Serial.println(now());
  print_date_time();
}
void print_date_time() { //easy way to print date and time
  char buf[40];
  sprintf(buf, "%02d/%02d/%4d %02d:%02d:%02d", day(), month(), year(), hour(), minute(), second());
  Serial.println(buf);
}

void loop() {
  static int minutes_past_midnight, last_print_time = 0;

  // check the clock
  minutes_past_midnight = hour() * 60 + minute();
  
  // every 5 minutes, print the data and time
  if (minutes_past_midnight != last_print_time && minutes_past_midnight % 5 == 0) {
    last_print_time = minutes_past_midnight;
    print_date_time();
  }
}

Which is fine except if you're working with an ESP32. Then, better techniques exist.

1 Like

I'm using a Nano, with no time library, so far.
Since I'm getting the time string from the GSM, I can use and display the date/time elements.
It's just Timezone+/- hours off.

Per my post, the time string is coming from a GSM module.

Then @jremington's approach is a good way to go.

Thanks much Jremington,

Looks like I can use the DST adjustment method for the Time Zone offset I receive from the carrier.

Maybe useful

#include "TimeLib.h"

tmElements_t te;  //Time elements structure
time_t unixTime; // a time stamp

int yy, mo, dd, hh, mi, ss, tZone;
char inData[] = "24/11/10,16:55:41-20";

void setup()
{
  Serial.begin(115200);
  sscanf(inData, "%2d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d%3d", &yy, &mo, &dd, &hh, &mi, &ss, &tZone);
  te.Second = ss;
  te.Hour = hh;
  te.Minute = mi;
  te.Day = dd;
  te.Month = mo;
  te.Year = (yy + 2000) - 1970;
  unixTime =  makeTime(te);
  Serial.print("unixTime = ");
  Serial.println(unixTime);
  Serial.println((tZone * 15) / 60);
  setTime(unixTime + (tZone * 15 * 60));
  char buf[40];
  sprintf(buf, "%02d/%02d/%4d %02d:%02d:%02d", day(), month(), year(), hour(), minute(), second());
  Serial.println(buf);
}
void loop()
{
}
1 Like

Careful with this. (tZone * 15 * 60) will overflow the range of int (which is only 16 bits wide on the Nano) if the time zone is more than ±9 hours from UTC (e.g., China, Australia, Hawaii, and many more). Use something like (tZone * 15 * 60UL) instead.

1 Like

Thank you

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.