Display Local Time and UTC

I'm a real newbie to Arduino so please be patient with me!

My first project is using an Uno, a DS3231 RTC and a 20x4 LCD

After a few hours I finally got the code to work; my clock project displays date, time and temperature!

I thought it would be nice to add UTC time as well and I used t.hour-2 to display UTC time.
This works great, the only trouble is at midnight the time displays the hour as -1 and at 01h00 as -2
How can I display the correct time?

lcd.setCursor(0,2); //Go to third line of the LCD Screen

lcd.print("UTC Time ");

lcd.setCursor(11,2); //Start text at column 11 on third line

lcd.print(t.hour-2);
lcd.print(":");
if(t.min<10)
{
lcd.print("0");
}
lcd.print(t.min);
lcd.print(":");
if(t.sec<10)
{
lcd.print("0");
}
lcd.print(t.sec);
lcd.print(' ');

There is a difference between local time and UTC time. What you are trying to display is local time. That is NOT done by just subtracting 2 hours from the UTC time's hour value.

You need to look at the hour value. If it is 2 or more, subtract 2. If it less than 2, add 22 AND subtract one from the day value. Of course, that will get tricky on the last day of the month, especially on the last day of the year.

Better would be to google time zone offset, and find the Arduino code to deal with time zones. By getting the time as a time_t object, instead of a bunch of discrete values, you can easily subtract 2 hours, and then convert the time_t to a bunch of discrete values. And, therein lies a hint as to how the time zone code works.

PaulS:
There is a difference between local time and UTC time. What you are trying to display is local time. That is NOT done by just subtracting 2 hours from the UTC time's hour value.

You need to look at the hour value. If it is 2 or more, subtract 2. If it less than 2, add 22 AND subtract one from the day value. Of course, that will get tricky on the last day of the month, especially on the last day of the year.

Thank you Paul,

I want to display both times, local and UTC. UTC time is minus 2 hours from local time

I am displaying Local time on line 2 and UTC time on line 3 of my display, both showing okay.
The problem only occurs at midnight, UTC then displays -2 as the hour instead of 00 (12pm) and -1 instead of 01 (1am)
I understand UTC time is displaying what I can told it to display, I.E. local time minus 2 ( 0-2 at midnight and 1-2 at 1am).
How do I change my code to correct this error?

Paul said:

You need to look at the hour value. If it is 2 or more, subtract 2. If it less than 2, add 22 AND subtract one from the day value.

I think that should spark a flame.
You are right... -2:00 is not right.

Maybe later, we can talk about modulo math. (another way of dealing with this)

Jacques

Thank you for the replies....but I'm still none the wiser!

@MaggieMay23:

As you are new here, I will explain about posting code.

When you post code, please use code tags. Code tags make your code look

like this

when you post it.
To get code tags, click on the </> symbol in the row of icons at the top of the message input box. (The </> symbol is at the beginning of the row.)

Also, when you post code, please post your complete sketch. I noticed that the code you posted did not have this

void setup()

nor this

void loop()

therefore it could not have been a complete sketch.

Please post your complete sketch, using code tags, and then we will be able to give you better help.

Thank you for your patience and help.

Here is my code ...

#include <Wire.h>
#include <ds3231.h>
#define BUFF_MAX 128
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
  
uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 1000;

void setup()
{
    Wire.begin();
    DS3231_init(DS3231_INTCN);
    memset(recv, 0, BUFF_MAX);

 //***LCD Setup***
   lcd.begin (20,4);  // initialize the lcd 

 //   setTheTime("301810101092017");     // ssmmhhWDDMMYYYY set time once in the given format

}

void loop()
{
    char tempF[6]; 
    float temperature;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;
    // show time once in a while
    if (now - prev > interval){
        DS3231_get(&t); //Get time
        temperature = DS3231_get_treg(); //Get temperature
        dtostrf(temperature, 5, 1, tempF);

        lcd.clear();
        lcd.setCursor(0,0);
        
        lcd.print(t.mday);
        
       printMonth(t.mon);
              
        lcd.print(t.year);
        
        lcd.setCursor(0,1); //Go to second line of the LCD Screen
        lcd.print("Local Time ");
        lcd.print(t.hour);
        lcd.print(":");
        if(t.min<10)
        {
          lcd.print("0");
        }
        lcd.print(t.min);
        lcd.print(":");
        if(t.sec<10)
        {
          lcd.print("0");
        }
        lcd.print(t.sec);
        
        lcd.print(' ');
 
       lcd.setCursor(0,2); //Go to third line of the LCD Screen
       lcd.print("UTC Time ");
       lcd.setCursor(11,2); //Start text at column 11 on third line
       lcd.print(t.hour-2);
       lcd.print(":");
        if(t.min<10)
        {
          lcd.print("0");
        }
        lcd.print(t.min);
        lcd.print(":");
        if(t.sec<10)
        {
          lcd.print("0");
        }
        lcd.print(t.sec);
        lcd.print(' ');
        
        lcd.setCursor(0,3); //Go to fourth line of the LCD Screen
        lcd.print("Temperature");
        lcd.setCursor(12,3); //Go to column 12 on fourth line of the LCD Screen
        lcd.print(tempF);
        lcd.print(char(223));
        lcd.print("C ");
        prev = now;
       
    }

}

void setTheTime(char *cmd)
{
    struct ts t;

    // ssmmhhWDDMMYYYY  set time

        t.sec = inp2toi(cmd, 0);
        t.min = inp2toi(cmd, 2);
        t.hour = inp2toi(cmd, 4);
        t.wday = inp2toi(cmd, 6);
        t.mday = inp2toi(cmd, 7);
        t.mon = inp2toi(cmd, 9);
        t.year = inp2toi(cmd, 11) * 100 + inp2toi(cmd, 13);
        DS3231_set(t);
        Serial.println("OK");
}

void printMonth(int month)
{
  switch(month)
  {
    case 1: lcd.print(" January ");break;
    case 2: lcd.print(" February ");break;
    case 3: lcd.print(" March ");break;
    case 4: lcd.print(" April ");break;
    case 5: lcd.print(" May ");break;
    case 6: lcd.print(" June ");break;
    case 7: lcd.print(" July ");break;
    case 8: lcd.print(" August ");break;
    case 9: lcd.print(" September ");break;
    case 10: lcd.print(" October ");break;
    case 11: lcd.print(" November ");break;
    case 12: lcd.print(" December ");break;
    default: lcd.print(" Error ");break;
  } 
}

After these lines in your code:

    char tempF[6];
    float temperature;
    char buff[BUFF_MAX];
    unsigned long now = millis();
    struct ts t;

please insert this (see my comments, in the lines with the // marks):

    // declare some variables for our timekeeping calculations:
    // an int can hold whole numbers (integers) from -32768 to 32767
    // which, for what we are doing, is more than enough
    int localHour, utcHour;

The reason you insert that is to make this next part work.
This line in your code

        DS3231_get(&t); //Get time

is where your Arduino checks the DS3231 to find out what time it is.
Once it knows the time, then we can perform some calculations, thus:

        // get the local hour
        localHour = t.hour;

        // subtract 2 hours from the local hour to get the UTC hour
        utcHour = localHour - 2;

        // does this give us a negative result? let's check:
        if (utcHour < 0)
        {
          // a negative number for the hour is unacceptable
          // so, if it's negative, we add 24 to make it positive
          utcHour += 24;
        }

Then the variable utcHour will have the value we want it to have so we can do things like this:

       // to print the UTC hour on the display:
       lcd.print(utcHour);

If you are not familiar with variables and how to use them, perhaps the other people in this forum could recommend a tutorial or guide for you.

@odometer
What does that code do if OP then wants to display the date, too?

@odometer

Thank you....Thank you!

You explained the code perfectly and now I see how it works.

@PaulS

I'm not too worried about the date, it was the negative time that I didn't like!

Thanks guys for all your help. I'm one happy person!

I'm not too worried about the date

You can get the day, month, year, hour, minute, and second values from the RTC. You can use them, and the TimeLib library to create a time_t object. You can subtract 2 hours from the time_t object. You can then convert the time_t object back to day, month, year, hour, minute, and second values, and the date WILL reflect the fact that you subtracted 2 hours.

@PaulS

Thank you

It makes more sense to set the RTC to UTC because it never varies.