Help with Arduino Programing Code to Convert UTC Time Zone into Local Time Zone

Hello there, Could anyone please help me with the Arduino code sketch to convert GPS module received UTC time zone into local time zone.

I am using this Arduino code sketch to get the GPS details on serial monitor, its showing only default UTC time zone. Please help in modifying the code with converting this UTC time zone to local Date/Time zone. Thanks.

  void displayInfo()
{
  Serial.print(F("Location: ")); 
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}

I recommend to use unix time and the Time library (TimeLib.h) for that purpose, as time zone corrections also involve date changes, which the library handles automatically.

Example:

//time_make_and_add
#include "TimeLib.h"

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

void setup() {
  Serial.begin(9600);
  // what is the current system time after startup?
  Serial.print("Startup: now() = "); //current time
  Serial.println((unsigned long) now());
  delay(3000);
  Serial.print("after 3s delay, now() = ");
  Serial.println((unsigned long) now());

  // display date_time in Arduino-speak
  Serial.print("day/date @startup+3s : ");
  Serial.print(day());
  Serial.print("/");
  Serial.print(month());
  Serial.print("/");
  Serial.print(year());
  Serial.print(" ");
  Serial.print(hour());
  Serial.print(":");
  Serial.print(minute());
  Serial.print(":");
  Serial.println(second());

  // new internal clock setting.
  // convert a date and time into unix time, offset 1970
  te.Second = 0;
  te.Hour = 23; //11 pm
  te.Minute = 0;
  te.Day = 1;
  te.Month = 1;
  te.Year = 2017 - 1970; //Y2K, in seconds = 946684800UL
  unixTime =  makeTime(te);
  Serial.print("Example 1/1/2017 23:00 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 += 7200UL; //add 2 hours
  setTime(unixTime);
  Serial.println("After adding 2 hours");
  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() {}

Hello @jremington, Thank you for your valuable reply. But actually i want to convert this from GPS received NEMA UTC time zone. I am successfully converting this with my above mentioned code, but it shows the Date/Time in UTC time zone. I want to add extra code lines for local time zone conversion within in the same mentioned code.

I have tired this code also, but it didn't work to convert UTC time to local time zone. Thanks.

if (gps.time.isValid())
      {
        TimeString = "";
        hour = gps.time.hour()+ 5; //adjust UTC
        minute = gps.time.minute()+30;
        second = gps.time.second();
    
        if (hour < 10)
        TimeString = '0';
        TimeString += String(hour);
        TimeString += " : ";

        if (minute < 10)
        TimeString += '0';
        TimeString += String(minute);
        TimeString += " : ";

        if (second < 10)
        TimeString += '0';
        TimeString += String(second);
      }

The code I posted shows you how to do that.

Instead of adding two hours as shown in the example, add or subtract the time difference between the desired time zone and UTC.

Furthermore, TimeLib.h can be set up to automatically synchronize with GPS time, obtained from your GPS receiver.

Your approach does not take midnight or date changes into account, and will be wrong much of the time.

Which time zone is your local time zone?
Does it use Daylight Saving Time for part of the year?

consider

 4:50:20
 9:50:20
 1:50:20
char s [40];

char *
getTimeStr (
    char *s,
    int   hour,
    int   min,
    int   sec,
    int   timezone )
{

    hour = (hour + timezone) % 24;

    sprintf (s, "%2d:%02d:%02d", hour, min, sec);
    return s;
}


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

    Serial.println (getTimeStr (s, 4, 50, 20, 0));
    Serial.println (getTimeStr (s, 4, 50, 20, 5));

    Serial.println (getTimeStr (s, 20, 50, 20, 5));
}

void loop() {
}

Hello @gcjr , Thanks for your reply with providing the code. May i know please where in your code is the local time zone conversion code from the GPS received UTC time zone? Thanking you.

Hello @odometer , Thanks for your response. My local time zone is IST (Indian Standard Time) and doesn't use Daylight Saving Time. Thanking you.

I have used this below mentioned sample code for adjusting GPS date and time to my local time zone, but it didn't work at all also?

#include <Time.h>             // Time Library
#include <TinyGPS++.h>        // GPS Library
#include <AltSoftSerial.h>    // Allows two Serial connections

// Set GPS RX and TX pins if using software serial connections.
// See below to use hardware serial connections

//static const int RXPin = 4, TXPin = 3;  // Example Uno
static const int RXPin = 48, TXPin = 46;  // Example Mega

static const uint32_t GPSBaud = 4800;       
//static const uint32_t GPSBaud = 9600;     

// The TinyGPS++ object
TinyGPSPlus gps;

// Serial connection to the GPS device
AltSoftSerial Serial_GPS;
//#define Serial_GPS Serial1  // Uncomment this line & comment
                              // above line to use a hardware
                              // Serial Port

// Change this value to suit your Time Zone
const int UTC_offset = 10;   // Eastern Australia Time

time_t prevDisplay = 0; // Count for when time last displayed

void setup()
{
  Serial.begin(9600);
  Serial_GPS.begin(GPSBaud); // Start GPS Serial Connection
  
  Serial.println("Waiting for GPS time ... ");
}

void loop()
{
  GPS_Timezone_Adjust();  // Call Time Adjust Function
}

void GPS_Timezone_Adjust(){
  
  while (Serial_GPS.available()) {
    if (gps.encode(Serial_GPS.read())) { 
      
      int Year = gps.date.year();
      byte Month = gps.date.month();
      byte Day = gps.date.day();
      byte Hour = gps.time.hour();
      byte Minute = gps.time.minute();
      byte Second = gps.time.second();

        // Set Time from GPS data string
        setTime(Hour, Minute, Second, Day, Month, Year);
        // Calc current Time Zone time by offset value
        adjustTime(UTC_offset * SECS_PER_HOUR);           
      
    }
  }
  
  // -- Delete this section if not displaying time ------- //
  if (timeStatus()!= timeNotSet) {
    if (now() != prevDisplay) {     
      prevDisplay = now();
      SerialClockDisplay();
    }
  }
  // -- Also delete the SerialClockDisplay()function ---- //
  
} // Keep

void SerialClockDisplay(){
  // Serial Monitor display of new calculated time - 
  // once adjusted GPS time stored in now() Time Library 
  // calculations or displays can be made.
  
  if (hour() < 10) Serial.print(F("0"));
        Serial.print(hour());
        Serial.print(F(":"));
  if (minute() < 10) Serial.print(F("0"));
        Serial.print(minute());
        Serial.print(F(":"));
  if (second() < 10) Serial.print(F("0"));
        Serial.print(second()); 
        
        Serial.print(" ");
  
  if (day() < 10) Serial.print(F("0"));      
        Serial.print(day());
        Serial.print(F("/"));
  if (month() < 10) Serial.print(F("0"));
        Serial.print(month());
        Serial.print(F("/"));
        Serial.println(year());
}

You calculate Indian Standard Time using the Arduino the same way you would calculate it using pen and paper.

Begin by adding 5 to the UTC hour to get the IST hour. Also add 30 to the UTC minutes to get the IST minutes. But we're not finished yet. Next, check to see whether the IST minute you have calculated is greater than 59. If it is, then you need to subtract 60 from the IST minutes and add 1 to the IST hours. We're still not finished. The next step is to check to see whether the IST hour you have calculated is greater than 23. If it is, then subtract 24 from the hour (and add 1 to the date, if you are counting days).

Like, after the place you wrote this

        TimeString = "";
        hour = gps.time.hour()+ 5; //adjust UTC
        minute = gps.time.minute()+30;
        second = gps.time.second();

try putting this:

        if (minute > 59) {
          minute = minute - 60;
          hour = hour + 1;
        }
        if (hour > 23) {
          hour = hour - 24;
        }
1 Like

Hello @odometer, Thank you for keep helping. I'll try with your modified code and update you with the same. Thanks.

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