Incorrect Unix time

I'm a noob and wrote an alarm clock sketch with my girls as a learning exercise. I'm quite sure it's laughably bad by any measure and is very basic to account for my (in)ability. Sorry but it's all I can do for now. I am using now.unixtime() and simply triggering an alarm loop when the now.unixtime = a target unix time. I wasn't sure how else to work with comparing times.

The human time displays correctly and is set on compiling from the host computer. However the Unix time is incorrect, and I presume is a result of the difference between my local time and UTC. I wondered if there was a way to have the correct unix time without affecting the local time?

I also wondered how I should be handling the times to do away with Unix time and working directly with human times while keeping the sketch fundamentally unchanged. While I'm sure it's shockingly bad, at least I can understand it :slight_smile:

I hope this is the correct way to share this code.

Thank you

#include <Wire.h> //loads I2C library
#include <LiquidCrystal_I2C.h> //loads LCD I2C library
#include <RTClib.h> //loads RTC library

RTC_DS1307 RTC;

LiquidCrystal_I2C lcd (0x3F,16,2); //I2C address of LCD, 16 characters, 2 lines

#define buz 13 //defining buzzer pin as pin 13
long alarmOn = 1536956950; //set alarm time in unixtime 

void setup()
{  
  Serial.begin(9600); //begin serial communications
  Wire.begin(); //begin I2C communications
  RTC.begin(); //begin RTC

  pinMode(buz, OUTPUT); //setup buz pin as an output

  lcd.begin(16,2); //setup lcd as 16x2 display
  lcd.backlight(); //turns on backlight   
  lcd.setCursor(0,0); //sets cursor to top left
  lcd.print("Nina and Fia's"); //print 1st line message
  lcd.setCursor(0,1); //set cursor to 2nd line
  lcd.print("   Alarm Clock"); //set second line message

//RTC.adjust(DateTime(__DATE__, __TIME__)); //Uncomment this line to set the date and time
  
  delay(5000); //startup message delay
  lcd.clear(); //clears screen after startup message
}

void loop()
{
  DateTime now = RTC.now(); //defines RTC?
  lcd.setCursor(0,0); //below displays time and date
  lcd.print("Time: ");
  lcd.print(now.hour());
  lcd.print(":");
  lcd.print(now.minute());
  lcd.setCursor(0,1);
  lcd.print("Date: ");
  lcd.print(now.day());
  lcd.print("/");
  lcd.print(now.month());
  lcd.print("/");
  lcd.print(now.year());
  {
  Serial.print(now.unixtime()); //print unix time to serial port
  Serial.println(); //advances one line on serial monitor
  delay(1000);
  }

if(now.unixtime() == alarmOn) //Compare the current time with the Alarm time, both in unixtime.
{
  for(int i=0; i<=10; i++)
  {
    lcd.clear(); //clears time and date
    lcd.print("  Nina and Fia"); //displays message
    lcd.setCursor(0,1);
    lcd.print("   WAKE UP!!!");
    digitalWrite(buz,HIGH); //turns buzzer on
    delay(1000);
    digitalWrite(buz, LOW);
    delay(1000);
    lcd.clear();
}
}
}

First a tip, press ctrl+T and see how that looks :slight_smile:

Next, did you ever printed DATE and TIME in order to see what time you set?

And you say it's wrong but you never give an example of why you think so. Aka, show us what serial monitor shows.

886014:
I wasn't sure how else to work with comparing times.

Basically exactly how you would do as a human :wink:
Is the alarm armed?
Is the current hour equal to the alarm hour?
Is the current minute equal to the alarm minute?

If yes to all it's time to trigger the alarm. (And of course can get extended or date / day of week etc.)

septillion:
Aka, show us what serial monitor shows.

I'm not sure I follow what you're asking for here? If I was to copy and paste the serial monitor time it would obviously be wrong as it's a live serial monitor.

The unix time as displayed on the serial monitor is incorrect when compared with what the correct unix time is at that particular point in time.

It's a snapshot, yeah. But you say the unixtime is wrong but you also print the time in "human" format. Or is that wrong as well?

PS You forgot to answer some questions :wink:

I didn't forget, I didn't understand what you are asking.

As indicated in the sketch, there is an I2C LCD display indicating the local time. As I mentioned in the original question, that is displaying the correct local time as set by the host computer.

Then say that, don't just skip over parts you didn't get...

So do:
Add in a print of the DATE end TIME which you use(d) to set the RTC. Aka:

RTC.adjust(DateTime(__DATE__, __TIME__));
Serial.println(F("Date and time:"));
Serial.println(__DATE__);
Serial.println(__TIME__);

And copy a full output of the serial monitor. I know it's not the time now but the problem is the difference between unixtime and "human" time, right?

Please read the original question, a complete description of the problem was fully described there.

Whether the time is displayed on the LCD or serial monitor makes no difference, if the time is displayed in dd/mm/yyyy it is correct in LOCAL TIME, if it is displayed in Unix Time, the latter is incorrect when compared to a Unix Time standard.

This is a serial print line

1537002229  9:3:49 15/9/2018

a complete description of the problem was fully described there.

No, it is not.

You can't seem to give an actual example of the problem. Why is that?

Please explain what the following sentence means and give an example. What is "a Unix Time standard"?

if it is displayed in Unix Time, the latter is incorrect when compared to a Unix Time standard.

Note: Unix time is defined as an approximation of the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970. Obviously, unless your time zone is 0, a correction will be involved.

jremington:
No, it is not.

You can't seem to give an actual example of the problem. Why is that?

Please explain what the following sentence means and give an example. What is "a Unix Time standard"?

Note: Unix time is defined as an approximation of the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970. Obviously, unless your time zone is 0, a correction will be involved.

Hi, thank you for your post. Please read the original question, a complete description of the problem was fully described there. I have highlighted the appropriate part to assist you.

The human time displays correctly and is set on compiling from the host computer. However the Unix time is incorrect, and I presume is a result of the difference between my local time and UTC. I wondered if there was a way to have the correct unix time without affecting the local time?

Google should be able to assist you with what is Unix Time.

If the Arduino/RTC is taking the RTC time (which is set as per the code provided) and converting it to seconds since 1/1/1970 without considering the time zone change between the RTC location and UTC then it is NOT Unix Time, therefore it is incorrect, as explained in the original post.

Gosh, did it never occur to you that you might have to add or subtract the time zone, to get your local time from UTC?

Who knows, you might even have to take into account "daylight savings time". If so, keep in mind the upcoming switch back! You know, the old "spring up, fall back" idea?

Good luck on your arduous journey.

PS: to get from your local time to UTC, you may have to perform the reverse operation, that is, if you subtract your time zone from UTC to get local time, add it back to local time to get UTC!

Simple, huh? Well, except when you pass midnight in the conversion, the date changes too, but that is way, way beyond the scope of this discussion.

jremington:
Gosh, did it never occur to you that you might have to add or subtract the time zone, to get your local time from UTC?

Who knows, you might even have to take into account "daylight savings time". If so, keep in mind the upcoming switch back! You know, the old "spring up, fall back" idea?

Good luck on your arduous journey.

PS: to get from your local time to UTC, you may have to perform the reverse operation, that is, if you subtract your time zone from UTC to get local time, add it back to local time to get UTC!

Simple, huh? Well, except when you pass midnight in the conversion, the date changes too, but that is way, way beyond the scope of this discussion.

Ah ok, sorry I didn't understand that you were also a beginner with Arduino, just like me, yes good luck on your journey too.

While I am new to Arduino, my background is electronics, so that's how I know the DS1307. No it doesn't require an adjustment from UTC to set the local time zone. The local time is set from this line of code. I also post that for you.

//RTC.adjust(DateTime(__DATE__, __TIME__)); //Uncomment this line to set the date and time

So this is the LOCAL time of the compiler? Simple huh? :wink:

So while the function is called "Unix Time" it seems it is in fact the number of seconds since 1/1/1970 on THAT RTC. Since THAT RTC is set to local time and it doesn't know what UTC is, unless it happened to be set to UTC, it isn't "UNIX Time" despite the label.

However since I don't know the libraries used in this application, there may be a function available within the library to set the difference between UTC and the RTC local time, thereby correcting the "Unix Time" to make it actually read correctly instead of it being a stupid label that doesn't actually mean what it says. On the other hand there may not be, and it needs to be done within the sketch. Somebody that knows about this library may be able assist beginners like us with that question, then we both continue with our journeys.

:slight_smile:

886014:
However since I don't know the libraries used in this application

All the source code for the libraries is on your computer. Perhaps the best thing to do, given your belligerent attitude, is to open the .h and .cpp files in a text editor and figure it out for yourself.

I don't know the libraries used in this application

It is quite useful to know which library you are using (including where you obtained it, because different libraries sometimes have the same name) and read through the documentation and/or source code. It can also be very instructive.

International time conversions have absolutely nothing to do with RTCs or Arduino.

gfvalvo:
All the source code for the libraries is on your computer. Perhaps the best thing to do, given your belligerent attitude, is to open the .h and .cpp files in a text editor and figure it out for yourself.

I am very polite on this thread and explained from the start that I am just a beginner trying and asking for help. Can you explain how you felt my question was "belligerent" and your post was somehow constructive?

It is quite useful to know which library you are using (including where you obtained it, because different libraries sometimes have the same name) and read through the documentation and/or source code. It can also be very instructive.

Ok thanks, I didn't know the libraries weren't unique. I'm not sure I'll understand much from looking in the RTC library, but I'll see if I can figure it out. Even if I did, I guess it would be easier to just make an adjustment in the sketch itself. This is just a stepping stone for learning in any case, I don't think using Unix Time is a very elegant solution.

I think the confusion has come from them naming it "Unix Time", when it's in fact it's not, or at least not normally. I guess it's easier to say than "time since 00:00 1/1/1970 on the computer on which the sketch was compiled" :wink:

You tell the Arduino
"Listen, whatever the time you read from the clock, treat it as if it is a unix timestamp.

That is what unixtime() method does.

There might be libraries that support timezones (never looked at it), maybe yours does as well. But timezones are tricky when it comes to daylight savings as the dates that they take affect varies from year to year, so I have my doubts; you will need a means to adjust those dates

The RTC time is set relative to your local timezone/DST settings using text format dates. So the RTC is running in local time.

RTC.adjust(DateTime(__DATE__, __TIME__)); //Uncomment this line to set the date and time

You are setting an alarm based on UTC (date with epoch 01.01.1970 00:00 UTC)

long alarmOn = 1536956950; //set alarm time in unixtime

Now you get a problem. You are assuming that the unixtime() method of a DateTime object will "know" the original timezone of that object (which is derived from the RTC time) and will respect that when performing the conversion. It does not. So you are mixing UTC times and local times in your comparison.

DateTime now = RTC.now(); //defines RTC?
. . .
if(now.unixtime() == alarmOn) //Compare the current time with the Alarm time, both in unixtime.
. . .

There are different approaches here. I use the Timezone library, configured for my local time zone rules, and always use UTC for internal /system times including the RTC etc. and compensate for the local time zone (including DST) only for entering or displaying information.
You could also "fix" it by adjusting alarmOn to compensate for your local timezone/DST settings.

886014:
This is a serial print line

1537002229  9:3:49 15/9/2018

jremington:
You can't seem to give an actual example of the problem.

He (she?) did, right there.

Note: Unix time is defined as an approximation of the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970.

This is true. Let's do a bit of arithmetic on the numbers in that Serial printed line.

Converting 1537002229 seconds to days, hours, minutes, and seconds yields 17789 days, 9 hours, 3 minutes, and 49 seconds. The given time of day is 09:03:49, which is exactly the same as the hours, minutes, and seconds from our conversion.

Obviously, unless your time zone is 0, a correction will be involved.

That is also true.

I do not know exactly which "RTClib.h" our friend is using, as there seems to be more than one in existence. Here is a link to the one I examined: GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library Unless I am mistaken, this library simply assumes that one's local time is UTC, and its unixtime() method calculates Unix time from local time on the basis of this assumption.

Almost certainly our friend made the (for a beginner) reasonable assumption that the unixtime() method would do what its name implies, which is to give Unix time. A reasonable assumption, yes, but as it turns out, it is a wrong assumption. It is wrong because the library author made an unreasonable assumption, which I have already gone over.

886014:
I also wondered how I should be handling the times to do away with Unix time and working directly with human times while keeping the sketch fundamentally unchanged.

Instead of this:

if(now.unixtime() == alarmOn) //Compare the current time with the Alarm time, both in unixtime.

try something like this:

// change these numbers to the wake-up time you want
byte wakeHour = 7;
byte wakeMinute = 30;

// This next line checks if it is time to wake up:
if ((now.hour() == wakeHour) && (now.minute() == wakeMinute) && (now.second() < 5))

If you are wondering about the (now.second() < 5) in that last line, it is because delays and other things in your code might occasionally cause your clock to skip a second, so rather than checking for one specific second (such as 7:30:00), I am giving the clock a window of a few seconds (in my example, 7:30:00 through 7:30:04).