Converting GPS UTC time to local time zone

I apologize for my ignorance but I'm very new to programming. I have tried searching every example I can find but nothing is working. I would like for the time output from the gps to be the local timezone of EST (-5) but everything I try continues to give me UTC. Here is my code.

#include <SoftwareSerial.h>

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <TinyGPSPlus.h>

byte last_second, Second, Minute, Hour, Day, Month;
int Year;


LiquidCrystal_I2C lcd(0x27, 20, 4);

// Initialize the OLED display with address 0x3C
TinyGPSPlus gps;  //defines the gps object

void setup() {
  Serial.begin(9600);   // This starts the global serial interface.  This is what is used for the majority of the functions.
  Serial3.begin(9600);  // This starts the GPS on the pin.  Anything to do with pin will be referenced as Serial3
  lcd.init();
}

void loop() {

  while (Serial3.available() > 0)
    gps.encode(Serial3.read());
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("Latitude: ");
  lcd.print(gps.location.lat());
  lcd.setCursor(1, 1);
  lcd.print("Longitude: ");
  lcd.print(gps.location.lng());
  lcd.setCursor(1, 2);
  lcd.print("Time:  ");
       byte Minute = gps.time.minute();
       byte Second = gps.time.second();
       byte Hour   = gps.time.hour();
       byte Day   = gps.date.day();
       byte Month = gps.date.month();
       byte Year  = gps.date.year();
       setTime(Hour, Minute, Second, Day, Month, Year);
       adjustTime(-5);
        
  lcd.setCursor(1, 3);
  lcd.print("Date:  ");
  lcd.print(gps.date.month());
  lcd.print("/");
  lcd.print(gps.date.day());
  lcd.print("/");
  lcd.print(gps.date.year());
  Serial.println("# of Satellites " + gps.satellites.value());
  Serial.println(gps.satellites.value());
  Serial.println(gps.location.lat());
  Serial.println(Hour);
  
}


For testing, I'm just sending the hour to the serial monitor. Once it is correct, I will update the lcd output.

Any assistance would be greatly appreciated!!

From my googling, it seems that adjustTime is to be in seconds, not hours.
Try:
adjustTime(-18000);

Thank you. That is what I had originally and then thought to try hours. Both were returning the UTC time.

It is like the offset is being ignored in the function

You are printing the variable Hour that you set from the GPS, not the hour from the real-time clock maintained by the Time library.

Yes, this is what is happening.
Try this instead:

Serial.println(hour());

Thank you. That is returning Hour can not be used as a function

Do you want the time to be corrected for daylight saving time changes ?
If so, look at the TimeZone library.

Which Arduino board are you using?

Use lowercase h for hour

Thank you. It is still returning the UTC time.

What is it giving you for the year? You are trying to fit the year into a byte. A byte can only go from 0 to 255. We are in the year 2024. I don't see how the number 2024 can fit into a byte.

it is returning 2024

Why are you declaring variables with these names at the top, like this

and then again declaring variables with these names here?

Do you want Year to be an int or a byte?

I would remove the word byte from those lines.

Try:

#include <SoftwareSerial.h>

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <TinyGPSPlus.h>

byte last_second, Second, Minute, Hour, Day, Month;
int Year;


LiquidCrystal_I2C lcd(0x27, 20, 4);

// Initialize the OLED display with address 0x3C
TinyGPSPlus gps;  //defines the gps object

void setup() {
  Serial.begin(9600);   // This starts the global serial interface.  This is what is used for the majority of the functions.
  Serial3.begin(9600);  // This starts the GPS on the pin.  Anything to do with pin will be referenced as Serial3
  lcd.init();
}

void loop() {

  while (Serial3.available() > 0)
    gps.encode(Serial3.read());
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("Latitude: ");
  lcd.print(gps.location.lat());
  lcd.setCursor(1, 1);
  lcd.print("Longitude: ");
  lcd.print(gps.location.lng());
  lcd.setCursor(1, 2);
  lcd.print("Time:  ");
       Minute = gps.time.minute();
       Second = gps.time.second();
       Hour   = gps.time.hour();
       Day   = gps.date.day();
       Month = gps.date.month();
       Year  = gps.date.year();
       setTime(Hour, Minute, Second, Day, Month, Year);
       adjustTime(-18000);
        
  lcd.setCursor(1, 3);
  lcd.print("Date:  ");
  lcd.print(gps.date.month());
  lcd.print("/");
  lcd.print(gps.date.day());
  lcd.print("/");
  lcd.print(gps.date.year());
  Serial.println("# of Satellites " + gps.satellites.value());
  Serial.println(gps.satellites.value());
  Serial.println(gps.location.lat());
  Serial.println(hour());
  
}

What does this get you? If this doesn't work, I have another approach you could use.

I went back and look at everything again. If I print gps.data.year I get 2024. Serial.println(year()); will give me 2024. If I print Year, it gives 232 as that is defined as an integer. That could just be removed.

it is still giving the UTC time.

One more time:

Try this and see if you like the results:

#include <SoftwareSerial.h>

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <TinyGPSPlus.h>

byte last_second, Second, Minute, Hour, Day, Month;
int Year;


LiquidCrystal_I2C lcd(0x27, 20, 4);

// Initialize the OLED display with address 0x3C
TinyGPSPlus gps;  //defines the gps object

void setup() {
  Serial.begin(9600);   // This starts the global serial interface.  This is what is used for the majority of the functions.
  Serial3.begin(9600);  // This starts the GPS on the pin.  Anything to do with pin will be referenced as Serial3
  lcd.init();
}

void loop() {

  while (Serial3.available() > 0)
    gps.encode(Serial3.read());
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("Latitude: ");
  lcd.print(gps.location.lat());
  lcd.setCursor(1, 1);
  lcd.print("Longitude: ");
  lcd.print(gps.location.lng());

  Minute = gps.time.minute();
  Second = gps.time.second();
  Hour   = gps.time.hour();
  Day   = gps.date.day();
  Month = gps.date.month();
  Year  = gps.date.year();

  // adjust for local time zone: UTC minus 5 hours
  // to avoid negative numbers in the calculation,
  // we do it by adding 19 hours and subtracting one day
  Hour += 19;
  Day--;

  // twenty-four hours make one day
  if (Hour >= 24) {
    Hour -= 24;
    Day++;
  }

  // change "zeroth" day of month to last day of previous month
  if (Day == 0) {
    Month--;
    if (Month == 0) {
      Month = 12;
      Year--;
    }
    if ((Month == 4) || (Month == 11) || (Month == 9) || (Month == 6)) {
      Day = 30;
    }
    else if (Month == 2) {
      if ((Year % 4) == 0) {
        // this will fail in the year 2100
        Day = 29;
      }
      else {
        Day = 28;
      }
    }
    else {
      Day = 31;
    }
  }

  setTime(Hour, Minute, Second, Day, Month, Year);

  lcd.setCursor(1, 2);
  lcd.print("Time:  ");
  lcd.print(Hour);
  lcd.print(":");
  if (Minute < 10) {
    lcd.print("0");
  }
  lcd.print(Minute);
  lcd.print(":");
  if (Second < 10) {
    lcd.print("0");
  }
  lcd.print(Second);
        
  lcd.setCursor(1, 3);
  lcd.print("Date:  ");
  lcd.print(Month);
  lcd.print("/");
  lcd.print(Day);
  lcd.print("/");
  lcd.print(Year);
  Serial.println("# of Satellites " + gps.satellites.value());
  Serial.println(gps.satellites.value());
  Serial.println(gps.location.lat());
  Serial.println(hour());
  
}

That worked!!!! Thank you so much!!! Now, I just have to wrap my head around the code :slight_smile:

I just did the conversion "the long way". I wanted to subtract 5 hours, but subtracting 5 could possibly result in a negative number (what if UTC hours were less than 5 when we did it?), so instead I added 19 hours, which would give the same time of day as subtracting 5 hours. Then I needed to take care of what happens if the hours end up being a number that is 24 or greater. Then the rest of the code is just to get the date right: think of what happens if adding or subtracting hours gets us into a different day.