Post Reply 
Calendar functions v.2
09-22-2018, 09:48 AM (This post was last modified: 09-23-2018 08:10 AM by JMB.)
Post: #1
Calendar functions v.2
This is a new enhanced version of my calendar functions; now these functions deal with time as well as with dates. The input of dates and time must follow the HP Prime syntax.

Valid dates must be entered in YYYY.MMDD format, in the range 1582.1015 to 9999.1231.
Valid times must be entered in HMS format. For example: 15°23'44" (15 h 23 min 44 s)

1 January 4713 BCE at 12:00 UTC is Julian Date 0.0
17 November 1858 CE at 00:00 UTC is Modified Julian Date 0.0

The user must set up two variables: TimeZone and DaylightSavingTime.
For example: TimeZone:=5°30' (UTC + 5.5 hours), DaylightSavingTime:=1 (1=DST on, 0=DST off)

Firmware version 2.0.0.13865 (2018 07 06) or higher is needed, because some functions rely on the new behavior of ROUND with numbers in HMS format.

Listing
PHP Code:
// Calendar functions
// JMB - September 2018

// Valid dates must be entered in YYYY.MMDD format, in the range 1582.1015 to 9999.1231
// Valid times must be entered in HMS format. For example: 15°23'44" (15 h 23 min 44 s)
// 1 January 4713 BCE at 12:00 UTC is Julian Date 0.0
// 17 November 1858 CE at 00:00 UTC is Modified Julian Date 0.0 
// The user must set up two variables: TimeZone and DaylightSavingTime.
// For example: TimeZone:=5°30' (UTC + 5.5 hours), DaylightSavingTime:=1 (1=DST on, 0=DST off) 

#pragma mode( separator(.,;) integer(h32) )

Date_to_JDNumber(d//Auxiliary function
// d:date → Julian Day Number
BEGIN
  
RETURN 2299161+DDAYS(1582.1015,d);
END;

JDNumber_to_Date(jdn//Auxiliary function
// jdn:Julian Day Number → date
BEGIN
  
RETURN DATEADD(1582.1015,jdn-2299161);
END;

Date_to_MJDNumber(d//Auxiliary function
// d:date → Modified Julian Day Number
BEGIN
  
RETURN DDAYS(1858.1117,d);
END;

MJDNumber_to_Date(mjdn//Auxiliary function
// mjdn:Modified Julian Day Number → date
BEGIN
  
RETURN DATEADD(1858.1117,mjdn);
END;
 
Convert_Date_Time(dt,s//Auxiliary function
// dt:{Local/UTC date, Local/UTC time}, s:-1/+1 → {UTC/Local date, UTC/Local time}
// Local to UTC: s = -1, UTC to Local: s = 1 
BEGIN
  LOCAL d 
:= dt(1);
  
LOCAL t := dt(2)+s*(TimeZone+DaylightSavingTime);
  IF 
0° THEN
    d 
:= DATEADD(d,-1);
    
:= t+24°;
  
END;
  IF 
t ≥ 24° THEN
    d 
:= DATEADD(d,1);
    
:= t-24°;
  
END;
  RETURN {
d,t};
END;

EXPORT Is_Date_Valid(d)
// d:date → 1=valid date, 0=invalid date
BEGIN
  
RETURN IFTE(1582.1015 OR 9999.1231 OR DAYOFWEEK(d) < 001);
END;

EXPORT Is_Leap_Year(d)
// d:date or year → 1=leap year, 0=ordinary year
BEGIN
  
RETURN DAYOFWEEK(IP(d)+0.0229) > 0;
END;

EXPORT Century(d)
// d:date or year → century
BEGIN
  
RETURN IP((d-1)/100)+1;
END;

EXPORT Year(d)
// d:date → year
BEGIN
  
RETURN IP(d);
END;

EXPORT Month(d)
// d:date → month
BEGIN
  
RETURN IP(FP(d)*100);
END;

EXPORT Day(d)
// d:date → day
BEGIN
  
RETURN FP(FP(d)*100)*100;
END;

EXPORT Day_of_Week(d)
// d:date → day of week
BEGIN
  LOCAL DoW 
:= {"Monday","Tuesday","Wenesday","Thursday","Friday","Saturday","Sunday"};
  
LOCAL day := DAYOFWEEK(d);
  IF 
day 0 THEN
    
RETURN "Invalid date";
  ELSE
    RETURN 
DoW(day);
  
END;
END;
 
EXPORT Day_Number_in_Year(d)
// d:date → day number within the year's date
BEGIN
  
IF IP(d) == 1582 THEN
    
RETURN DDAYS(1582.1015,d)+278;
  ELSE
    RETURN 
DDAYS(IP(d)+0.0101,d)+1;
  
END
END
;

EXPORT Week_Number(d)
// d:date → week number (ISO 8601)
BEGIN
  LOCAL yr 
:= Year(d), mn := Month(d), dy := Day(d);
  
LOCAL DoW_0101 := IFTE(yr == 15821DAYOFWEEK(yr+0.0101));  
  
LOCAL DoW_Yp1_0101 := IFTE(yr == 99996DAYOFWEEK(yr+1.0101));
  
LOCAL wn := IP((IFTE(yr == 1582Date_to_JDNumber(d)-2298884DDAYS(yr+0.0101,d))+DoW_0101-1)/7);
  IF 
mn == 12 AND DoW_Yp1_0101 ≤ 4 AND (32-dy) < DoW_Yp1_0101 THEN
    
RETURN 1;
  ELSE
    IF 
DoW_0101 ≤ 4 THEN
      
RETURN wn+1;
    ELSE
      IF 
mn == AND (9-dy) > DoW_0101 THEN
        
RETURN Week_Number(yr-1+0.1231);
      ELSE
        RETURN 
wn;
      
END;
    
END;
  
END;
END;

EXPORT Easter(y)
// y:year → date of Easter Sunday
BEGIN
  LOCAL a
,b,c,d,e,f,g;
  
LOCAL h,i,k,l,m,n;
  CASE
    IF 
1582 THEN
      
RETURN 0
    
END;
    IF 
== 1582 THEN
      
RETURN 1582.0415;
    
END;
    IF 
1582 THEN
      a 
:= irem(y,19);
      
:= iquo(y,100);
      
:= irem(y,100);
      
:= iquo(b,4);
      
:= irem(b,4);
      
:= iquo(b+8,25);
      
:= iquo(b-f+1,3);
      
:= irem(19*a+b-d-g+15,30);
      
:= iquo(c,4);
      
:= irem(c,4);
      
:= irem(32+2*e+2*i-h-k,7);
      
:= iquo(a+11*h+22*l,451);
      
:= h+l-7*m+114;
      RETURN 
iquo(n,31)/100 + (irem(n,31)+1)/10000;
    
END;
  
END;
END;

EXPORT Local_to_UTC(dt)
// dt:{Local date, Local time} → {UTC date, UTC time}
BEGIN
  
RETURN Convert_Date_Time(dt,-1);
END;

EXPORT UTC_to_Local(dt)
// dt:{UTC date, UTC time} → {Local date, Local time}
BEGIN
  
RETURN Convert_Date_Time(dt,1);
END;

EXPORT UTC_to_JD(dt)
// dt:{UTC date, UTC time} → Julian Date
BEGIN
  
RETURN Date_to_JDNumber(dt(1)) - 0.5 HMS→(dt(2))/24;
END;

EXPORT JD_to_UTC(jd)
// jd:Julian Date → {UTC date, UTC time}
BEGIN
  LOCAL jdn 
:= IP(jd), := FP(jd);
  IF 
t ≥ 0.5 THEN
    jdn 
:= jdn+1;
    
:= →HMS((t-0.5)*24);
  ELSE
    
:= →HMS(t*24+12);
  
END;
  RETURN {
JDNumber_to_Date(jdn),ROUND(t,4)};
END;  

EXPORT Local_to_JD(dt)
// dt:{Local date, Local time} → Julian Date
BEGIN
  
RETURN UTC_to_JD(Local_to_UTC(dt));  
END;  

EXPORT JD_to_Local(jd)
// jd:Julian Date → {Local date, Local time}
BEGIN
  
RETURN UTC_to_Local(JD_to_UTC(jd));
END;  

EXPORT JD_to_MJD(jd)
// jd:Julian Date → Modified Julian Date
BEGIN
  
RETURN jd-2400000.5;
END;

EXPORT MJD_to_JD(mjd)
// mjd:Modified Julian Date → Julian Date
BEGIN
  
RETURN mjd+2400000.5;
END;

EXPORT UTC_to_MJD(dt)
// dt:{UTC date, UTC time} → Modified Julian Date
BEGIN
  
RETURN Date_to_MJDNumber(dt(1)) + HMS→(dt(2))/24;
END;

EXPORT MJD_to_UTC(mjd)
// mjd:Modified Julian Date → {UTC date, UTC time}
BEGIN
  
RETURN {MJDNumber_to_Date(IP(mjd)),ROUND(→HMS(FP(mjd)*24),4)};
END;

EXPORT Local_to_MJD(dt)
// dt:{Local date, Local time} → Modified Julian Date
BEGIN
  
RETURN UTC_to_MJD(Local_to_UTC(dt));
END;

EXPORT MJD_to_Local(mjd)
// mjd:Modified Julian Date → {Local date, Local time}
BEGIN
  
RETURN UTC_to_Local(MJD_to_UTC(mjd));
END;

EXPORT Now
// → {{Local date, Local time}, {UTC date, UTC time}, Julian Date, Modified Julian Date}
BEGIN
  LOCAL d 
:= Date:= Time;
  RETURN {{
d,t},Local_to_UTC({d,t}),Local_to_JD({d,t}),Local_to_MJD({d,t})};
END;

EXPORT Now_Local
// → {Local date, Local time}
BEGIN
  LOCAL n 
:= Now;
  RETURN 
n(1);
END;

EXPORT Now_UTC
// → {UTC date, UTC time}
BEGIN
  LOCAL n 
:= Now;
  RETURN 
n(2);
END;

EXPORT Now_JD
// → Julian Date
BEGIN
  LOCAL n 
:= Now;
  RETURN 
n(3);
END;

EXPORT Now_MJD
// → Modified Julian Date
BEGIN
  LOCAL n 
:= Now;
  RETURN 
n(4);
END

Here are some examples based on Summer Central European Time. The variables TimeZone and DaylightSavingTime are set up to:

TimeZone:=1°
DaylightSavingTime:=1

Examples:

Is_Date_Valid(2018.0401) → 1
Is_Date_Valid(2018.0229) → 0

Is_Leap_Year(2018.0401) → 0
Is_Leap_Year(2018) → 0
Is_Leap_Year(2016.0401) → 1
Is_Leap_Year(2016) → 1

Century(2018.0401) → 21
Century(2018) → 21

Year(2018.0401) → 2018
Month(2018.0401) → 4
Day(2018.0401) → 1

Day_of_Week(2018.0921) → "Friday"
Day_Number_in_Year(2018.0921) → 264
Week_Number(2018.0921) → 38

Easter(2019) → 2019.0421

Local_to_UTC({2018.1215, 01°12'43"}) → {2018.1214, 23°12'43"}
UTC_to_Local({2018.1214, 23°12'43"}) → {2018.1215, 01°12'43"}

UTC_to_JD({2018.1214, 23°12'43"}) → 2458467.46716
JD_to_UTC(2458467.46716) → {2018.1214, 23°12'43"}
Local_to_JD({2018.1215, 01°12'43"}) → 2458467.46716
JD_to_Local(2458467.46716) → {2018.1215, 1°12'43"}

MJD_to_JD(0) → 2400000.5
JD_to_MJD(2400000.5) → 0

UTC_to_MJD({2018.1214, 23°12'43"}) → 58466.9671644
MJD_to_UTC(58466.9671644) → {2018.1214, 23°12'43"}
Local_to_MJD({2018.1215, 01°12'43"}) → 58466.9671644
MJD_to_Local(58466.9671644) → {2018.1215, 1°12'43"}

Now → {{2018.0922, 11°30'19"}, {2018.0922, 9°30'19"}, 2458383.89605, 58383.3960532}


Attached File(s)
.hpprgm  Calendar_v2.hpprgm (Size: 15.41 KB / Downloads: 34)

Josep Mollera. HP PRIME, HW: C, SW: 2.1.14730 (2023 04 13).
Find all posts by this user
Quote this message in a reply
09-22-2018, 10:03 AM
Post: #2
RE: Calendar functions v.2
Thanks for this enhancement of your first program !

Gérard.
Find all posts by this user
Quote this message in a reply
Post Reply 




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