Post Reply 
epoch Prime
01-05-2018, 05:00 PM (This post was last modified: 01-05-2018 05:40 PM by salvomic.)
Post: #1
epoch Prime
hi,
following an idea by Bill Duncan (see this MoHPC thread), is there anyone so kind to help me to make a program (or a set of commands) to get:
• current date and time -> epoch (Unix)
• epoch -> current date and time
• any date_and_time -> epoch and reverse
giving to the user the option to set Time Zone also?
The program should also avoid the "2038 bit overflow"...
The goal is to use when possible built-in commands, for precision purpose.

It a simple but useful idea to control epoch offline (when one is controlling logs or other things or for funny). I'm using the Bill's program in HP-41CX and also in Free42s. Now I thought to make something for the Prime, but not only by myself Smile

Thank you
Salvo

EDIT: an online tools is here.

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 06:03 PM (This post was last modified: 01-05-2018 06:06 PM by pier4r.)
Post: #2
RE: epoch Prime
Well epoch is from the 1st Jan 1970 00.00 if I am not mistaken.

Now -> epoch
Then one has to count the days until today, caring for leap years.
(this means caring also on the various lengths of different months)
Once one has the days. Days*86400 plus the seconds passed today.

date ->epoch
Same thing as above, but assuming that "now" is date.

epoch-> date
take the epoch and check how many days it fits.
Then check how many of those days fit years (considering leap years).
Then check how the rest of the days (after one has the number of years) fits in months (considering the different length of months).
Then once one has the remaining days , while year and month are identified, find the day and the hour.

The tedious (but crucial) part would be: leap years algorithm and months definition.

Timezone. Nah, too much work: https://en.wikipedia.org/wiki/List_of_tz...time_zones.
UTC and then the user can do a sum or subtraction alone.

Wikis are great, Contribute :)
Find all posts by this user
Quote this message in a reply
01-05-2018, 06:17 PM
Post: #3
RE: epoch Prime
thanks pier4r, we must also consider "leap seconds" (see Wikipedia)...

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 07:30 PM (This post was last modified: 01-05-2018 07:45 PM by Dieter.)
Post: #4
RE: epoch Prime
(01-05-2018 06:03 PM)pier4r Wrote:  Now -> epoch
Then one has to count the days until today, caring for leap years.
(this means caring also on the various lengths of different months)
Once one has the days. Days*86400 plus the seconds passed today.

You don't have to count anything, let alone handle different month lengths. There are well-known formulas that take all this into account. Simply calculate the Julian day number for two dates and you're done.

(01-05-2018 06:03 PM)pier4r Wrote:  The tedious (but crucial) part would be: leap years algorithm and months definition.

Not at all.
Maybe you want to look at this HP35s program to see how easy all this can be done.

(01-05-2018 06:03 PM)pier4r Wrote:  epoch-> date
take the epoch and check how many days it fits.
Then check how many of those days fit years (considering leap years).
Then check how the rest of the days (after one has the number of years) fits in months (considering the different length of months).
Then once one has the remaining days , while year and month are identified, find the day and the hour.

Waayyyy too complicated. ;-)

The key is the conversion between dates and Julian day numbers. And this can be done easily on the Prime since, as far as I know, it has the required commands to add days to a calendar date or determine the difference between two days.

Example (date taken from the Wikipedia page on Unix time): Between 1 Jan 1970 and 17 Sept 2004 there were 12678 days (can be calculated directly with the according Prime command). This times 86400 gives Unix time 1095379200. Add the remaining seconds of the day and you're done.

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 07:42 PM
Post: #5
RE: epoch Prime
(01-05-2018 07:30 PM)Dieter Wrote:  ... Simply calculate the Julian day number for two dates and you're done.

...

Dieter

Something like the formula used in my Astrolabio (Effemeridi), after Astrolab by Marcel Pelletier, maybe...
Code:

EXPORT julianDay(lista)
// lista like dateshortlist
BEGIN
  LOCAL y,m,d,a,b, JD;
  y:=lista(1);
  m:=lista(2);
  d:=lista(3);
  IF (m=1 OR m=2) THEN
  y:=y-1;
  m:=m+12
  END;
  IF y*100+m+d>=158225 THEN
  a:=IP(ABS(y/100));
  b:=2-a+IP(a/4);
  ELSE
  b:=0
  END;
  JD:=IP(365.25*(y+4716))+IP(30.6001*(m+1))+d+b-1524.5;
  RETURN JD;
END;

where "lista" is based on
Code:

dateshortlist:= MAKELIST(X,X,1,3);
and so on...

Salvo

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 07:51 PM (This post was last modified: 01-05-2018 07:54 PM by Dieter.)
Post: #6
RE: epoch Prime
(01-05-2018 07:42 PM)salvomic Wrote:  Something like the formula used in my Astrolabio (Effemeridi), after Astrolab by Marcel Pelletier, maybe...

I have no idea what this MAKELIST command does or how to handle lists on the Prime, but the implemented idea seems to calculate some kind of JDN.

However, I don't know if the line that checks whether a date is before or after 15 Oct 1582 (switch from Julian to Gregorian calendar) is correct. But this can be omitted anyway since in 1582 there was no Unix. At least as far as I know. ;-)

But again: You do not have to do this manually. IIRC since 2015 the Prime includes the required commands, e.g. DDAYS and DATEADD. Take a look at the manual.

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 08:07 PM (This post was last modified: 01-05-2018 08:34 PM by salvomic.)
Post: #7
RE: epoch Prime
(01-05-2018 07:51 PM)Dieter Wrote:  However, I don't know if the line that checks whether a date is before or after 15 Oct 1582 (switch from Julian to Gregorian calendar) is correct. But this can be omitted anyway since in 1582 there was no Unix. At least as far as I know. ;-)
No, I think there was no Unix in 1582 Big Grin
Quote:... You do not have to do this manually. IIRC since 2015 the Prime includes the required commands, e.g. DDAYS and DATEADD. Take a look at the manual.

yes, I know those functions, definitely, and I suggested to use them to make the program...

as far as the MAKELIST and "lista", the list is intended so:
• with listnow() we get the time now, i.e. {2018,1,5.87368055555} where the fraction .8736 is the time in /24
• so julianday({2018,1,5.87368055555}) or julianday(listnow) returns 2458124.37368, the Julian Date.

Other astronomical date functions in Effemeridi and Astrolab 4 app ...

EDIT: following your idea to use Julian Day, I tried this:
• julianday({1970,1,1}) -> 2440587.5
• julianday(listnow) -> 2458124.38559 :: in the same time I started the Bill's program (EPOCH) on my HP-41CX, calculated for my time zone (+1h) with 3600 in 00 register and it returned epoch = 1515183311
• (2458124.38559-2440587.5) (julianday now - Julianday 1970 Jan 1), that is 17536.8559 days
• 86400*17536.8559 returns 1515186914.98
last result is 3603.98 secs greater that EPOCH program: something went wrong: about 1 hour, and this should be the GMT difference.

So we should assemble these data to get epoch, but perhaps there is a way more concise to get it...

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 08:47 PM (This post was last modified: 01-05-2018 09:22 PM by Dieter.)
Post: #8
RE: epoch Prime
(01-05-2018 08:07 PM)salvomic Wrote:  EDIT: following your idea to use Julian Day, I tried this:
• julianday({1970,1,1}) -> 2440587.5

Please note that the Julian day number as it is used in astronomy refers to noon (12:00) for integer values, not midnight.

But why don't you simply try DDAYS(1970.0101, 2018.0105) to get the number of days since then (=17536), multiply this by 86400 (=1515110400) and finally add the seconds of the current time (3600*hours + 60*minutes + seconds)? It's really as simple as that. ;-)

And forget about times zones now. You can add that later once the calculation is finished.

(01-05-2018 08:07 PM)salvomic Wrote:  • julianday(listnow) -> 2458124.38559 :: in the same time I started the Bill's program (EPOCH) on my HP-41CX, calculated for my time zone (+1h) with 3600 in 00 register and it returned epoch = 1515183311

That's 72911 seconds more than 1515110400, so this looks like 20:15 and 11 seconds.

(01-05-2018 08:07 PM)salvomic Wrote:  last result is 3603.98 secs greater that EPOCH program: something went wrong: about 1 hour, and this should be the GMT difference.

Maybe this difference of 4 s is related to leap seconds between 1970 and today? But no... this should be more than just four.

Edit: I had another idea, but then I saw that you had one of the numbers wrong (17536.8559 instead of 17536.38559) so I deleted this again.

But what about a defined test case now? You didn't say for what date and exact time you want to calculate the epoch. Is it today 20:15.11 or something different?

BTW, when you quote a post: take a look at the "dateline" value in the editor. ;-)

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 09:10 PM (This post was last modified: 01-05-2018 09:25 PM by salvomic.)
Post: #9
RE: epoch Prime
(01-05-2018 08:47 PM)Dieter Wrote:  Please note that the Julian day number as it is used in astronomy refers to noon (12:00) for integer values, not midnight.
Definitely
(01-05-2018 08:47 PM)Dieter Wrote:  But why don't you simply try DDAYS(1970.0101, 2018.0105) to get the number of days since then (=17536), multiply this by 86400 (=1515110400) and finally add the seconds of the current time (3600*hours + 60*minutes + seconds)? It's really as simple as that. ;-)
Right.
Then we can use the variables Date and Time from the Prime (Vars catalog, or to write them with the first uppercase), so:
Code:
86400*(DDAYS(1970.0101,Date))+3600*HMS➝(Time)
is the same as
Code:
86400*(julianday(listnow)-2440587.5)
That's epoch(), right?
However the result returned is about +3600 secs from the result of Bill's EPOCH calculated for UTC+1 (3600 in 00)...
Subtracting 3600 we get the Epoc for GMT.
(01-05-2018 08:47 PM)Dieter Wrote:  Maybe this difference of 4 s is related to leap seconds between 1970 and today? But no... this should be more than just four.

or maybe simply the difference in the execution time between HP41CX (a bit more slow) and the Prime...

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 09:27 PM (This post was last modified: 01-05-2018 09:29 PM by Dieter.)
Post: #10
RE: epoch Prime
(01-05-2018 09:10 PM)salvomic Wrote:  
Code:
86400*(DDAYS(1970.0101,Date))+3600*HMS➝(Time)
is the same as
Code:
86400*(julianday(listnow)-2440587.5)

Hmmm... I am quite sure there was no "3600" when I started answering your post. So I wrote:

"I'm not sure how the Prime's HMS➝() command works, but I gues s it returns hours while you need seconds. Convert the time in h.ms format to decimal hours, then multiply this by 3600. Add these seconds to 86400*DDAYS(...)."

But it looks like you have corrected this already.

(01-05-2018 09:10 PM)salvomic Wrote:  That's epoch(), right?

I would guess so. ;-)

(01-05-2018 09:10 PM)salvomic Wrote:  However the result returned is about +3600 secs from the result of Bill's EPOCH calculated for UTC+1 (3600 in 00)...

Are you sure both of your programs refer to the same time zone?

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 09:36 PM (This post was last modified: 01-05-2018 09:39 PM by salvomic.)
Post: #11
RE: epoch Prime
(01-05-2018 09:27 PM)Dieter Wrote:  I'm not sure how the Prime's HMS➝() command works, but I gues s it returns hours while you need seconds. Convert the time in h.ms format to decimal hours, then multiply this by 3600. Add these seconds to 86400*DDAYS(...).
Time returns 22°28'52'' (read "h" for "°")
HMS➝(Time) return 22.481944444
so, it convert to hh+mm/60+ss/3600 I think...
(01-05-2018 09:27 PM)Dieter Wrote:  [quote='salvomic' pid='87952' dateline='1515186643']

Are you sure both of your programs refer to the same time zone?

I modified Bill's program changing the second instruction from -18000 to +3600 trying to get UTC+1 (instead of his statement; Bill in that thread wrote: «Seconds relative to GMT. Time zone given is Eastern Standard Time») and the result of EPOCH in HP41CX is equal to that in this web site
, so I think it return GMT value and not local time...
The Prime returns one hour more, that should be the real local time.

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 09:40 PM
Post: #12
RE: epoch Prime
(01-05-2018 07:30 PM)Dieter Wrote:  The key is the conversion between dates and Julian day numbers. And this can be done easily on the Prime since, as far as I know, it has the required commands to add days to a calendar date or determine the difference between two days.

Ah well, I did not check for that. Good to know. I remember I discovered the DDAYS function on the 50g (like in Nov 2017) that is pretty neat from time to time.

Wikis are great, Contribute :)
Find all posts by this user
Quote this message in a reply
01-05-2018, 09:44 PM
Post: #13
RE: epoch Prime
(01-05-2018 09:40 PM)pier4r Wrote:  I remember I discovered the DDAYS function on the 50g (like in Nov 2017) that is pretty neat from time to time.

DDAYS is also in HP-41CX, that has also DATE, DATE+, TIME... and in HP 42s (then in DM42)...

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 09:56 PM (This post was last modified: 01-05-2018 09:59 PM by Dieter.)
Post: #14
RE: epoch Prime
(01-05-2018 09:44 PM)salvomic Wrote:  DDAYS is also in HP-41CX, that has also DATE, DATE+, TIME... and in HP 42s (then in DM42)...

Date functions were already available in HP's first business calculator, the HP80.
But the HP42s does not offer date functions. Unlike Free42 and DM42.

And then take a look at the WP34s. Here you can even calculate Julian day numbers. ;-)

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 10:07 PM (This post was last modified: 01-05-2018 10:10 PM by Dieter.)
Post: #15
RE: epoch Prime
(01-05-2018 09:36 PM)salvomic Wrote:  I modified Bill's program changing the second instruction from -18000 to +3600 trying to get UTC+1 (instead of his statement; Bill in that thread wrote: «Seconds relative to GMT. Time zone given is Eastern Standard Time») and the result of EPOCH in HP41CX is equal to that in this web site
, so I think it return GMT value and not local time...
The Prime returns one hour more, that should be the real local time.

Taking a look at Bill's program it becomes clear that the time zone is subtracted at the end of the calculation. This means: you enter a time in your local time zone (or have the calculator take the current date/time from its clock) and the resulting epoch value refers to UTC (or GMT, if you prefer). So it is clear why Bill's EPOCH program returns 3600 seconds less.

As far as I know Unix time indeed refers to UTC, so this is the correct way to handle this. You may do so as well and subtract your local timezone (+3600 s) at the end.

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 10:16 PM
Post: #16
RE: epoch Prime
(01-05-2018 10:07 PM)Dieter Wrote:  Taking a look at Bill's program it becomes clear that the time zone is subtracted at the end of the calculation. This means: you enter a time in your local time zone (or have the calculator take the current date/time from its clock) and the resulting epoch value refers to UTC (or GMT, if you prefer). So it is clear why Bill's EPOCH program returns 3600 seconds less.

As far as I know Unix time indeed refers to UTC, so this is the correct way to handle this. You may do so as well and subtract your local timezone (+3600 s) at the end.

Dieter

Well!
I'm trying with these data and with DATEADD() to get the date from epoch()...
Thanks Dieter.

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-05-2018, 10:48 PM
Post: #17
RE: epoch Prime
(01-05-2018 10:16 PM)salvomic Wrote:  I'm trying with these data and with DATEADD() to get the date from epoch()...

That's easy:

epoch = 1515183311
IP(epoch/86400) = 17536; DATEADD(1970.0101, 17536) = 2018.0105
epoch mod 86400 = 72911; 72911/3600 = 20,25305555... or (HMS) 20:15'11"

If you want to get your local time, add your timezone first, i.e. in your case do the calculation for (epoch+3600).

Dieter
Find all posts by this user
Quote this message in a reply
01-05-2018, 11:26 PM
Post: #18
RE: epoch Prime
ok, tomorrow I'll see for your solution.
In the meantime I coded this:
Code:

EXPORT epoch()
BEGIN
RETURN 86400*(DDAYS(1970.0101,Date))+3600*HMS→(Time)-3600;
END;

EXPORT epoch2date(ep)
BEGIN
local dd, da, hh, mm, ss;
local yy, mt, dy;
dd:=ep/86400;
da:=DATEADD(1970.0101, IP(dd));
hh:=IP(24*FP(dd));
mm:=IP(60*FP(24*FP(dd)));
ss:=IP(60*FP(60*FP(24*FP(dd))));
yy:=IP(da);
mt:=IP(100*(FP(da)));
dy:=IP(100*FP(100*FP(da)));
RETURN({yy,mt,dy,hh,mm,ss});
END;

maybe it's redundant a lot...
How to make an optional parameter to input (or not) the time zone in epoch()?
I would like to make a versatile function that accept optional parameters: with nothing return epoch for the current date in GMT, with (mydate, myzone) returns a date and a zone...
Then I'll see to return for epoch2date both a "pretty formatted date" and a "calc date" as {2018.0105, 23,9721} for date and time.fractional...

Salvo

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
01-06-2018, 08:53 AM (This post was last modified: 01-06-2018 09:29 AM by Dieter.)
Post: #19
RE: epoch Prime
(01-05-2018 11:26 PM)salvomic Wrote:  
Code:
EXPORT epoch2date(ep)
BEGIN
local dd, da, hh, mm, ss;
local yy, mt, dy;
dd:=ep/86400;
da:=DATEADD(1970.0101, IP(dd));
hh:=IP(24*FP(dd));
mm:=IP(60*FP(24*FP(dd)));
ss:=IP(60*FP(60*FP(24*FP(dd))));
yy:=IP(da);
mt:=IP(100*(FP(da)));
dy:=IP(100*FP(100*FP(da)));
RETURN({yy,mt,dy,hh,mm,ss});
END;

maybe it's redundant a lot...

Maybe. But first of all you generally should not calculate a mod b by means of b*fp(a/b). This causes roundoff errors. There is a mod command that handles this exactly.

And then you do not have to calculate hours, minutes and seconds manually. Your method also works with fp(ep/86400) which again causes roundoff errors. I assume the Prime has a command that converts decimal hours to h.ms.

I would code it this way (you'll have to translate this to PPL):

yr = IP(da)
mt = IP(100 * da) mod 100
dy = IP(10000 * da) mod 100

And the same way for the time given as hh.mmss:

hours = (ep mod 86400)/3600
hhmmss = hms(hours)
hh = IP(hhmmss)
mm = IP(100 * hhmmss) mod 100
ss = IP(10000 * hhmmss) mod 100

BTW, does the Prime have a command for integer division? Like "DIV" or "\" in other programming languages?

(01-05-2018 11:26 PM)salvomic Wrote:  How to make an optional parameter to input (or not) the time zone in epoch()?
I would like to make a versatile function that accept optional parameters:

This can be answered by the Prime experts. I only can say how this could be done in VBA where parameters can be declared "optional". ;-)

(01-05-2018 11:26 PM)salvomic Wrote:  Then I'll see to return for epoch2date both a "pretty formatted date" and a "calc date" as {2018.0105, 23,9721} for date and time.fractional...

You may return time and date according to ISO 8601: 2018-01-06T10:29:35+01:00

Dieter
Find all posts by this user
Quote this message in a reply
01-06-2018, 09:28 AM
Post: #20
RE: epoch Prime
(01-06-2018 08:53 AM)Dieter Wrote:  ...
Or you could return something according to the ISO standard.

Dieter

Right!
However, I'll write a simple pretty_date() function to convert the Prime output (2018.0106, 2.0181145) in yy mm dd, hh mm ss.frac

At the moment the simplified program (with MOD) is:
Code:

// Epoch Unix time from 1970 Jan 1. Inspired by a Bill Duncan's program for HP-41CX
// Thanks to Dieter

// Epoch seconds in UTC time
EXPORT epoch()
BEGIN
RETURN 86400*(DDAYS(1970.0101,Date))+3600*HMS→(Time)-3600;
END;

EXPORT epoch2date(epoch)
BEGIN
local da, ti;
da:=DATEADD(1970.0101, IP(epoch/86400));
ti:=(epoch MOD 84600)/3600;
RETURN({da, ti});
END;

// EXPORT pretty_date({yymmdd,hhmmss})
// BEGIN
// local aa;
//
// RETURN();
// END;

Now here local time is 10:25
epoch() returns 1515230706
epoch2date(1515230706) returns {2018.0106, 12.41833333}
→HMS(12.41833333) returns 12°25'06'', that two hours later, but still I must set UTC problem...

Salvo

∫aL√0mic (IT9CLU) :: HP Prime 50g 41CX 71b 42s 39s 35s 12C 15C - DM42, DM41X - WP34s Prime Soft. Lib
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 5 Guest(s)