01-28-2015, 08:24 PM
Since date functions and calendar programs seem to be en vogue these days, here is my contribution for the HP35s. It is essentially a small program that converts between common calendar dates and Julian day numbers. This allows for all essential date related functions:
You can now imagine that JDNs make date related calculations very easy - as they are plain integers you can use simple addition and subtraction. Dividing a JDN by 7 yields a remainder that stands for the weekday of that date. Here is a program that does all this. Just to be sure: of course RPN mode is assumed. And be sure not to confuse x<>y (exchange stack registers x and y) and x<> Y (exchange x and variable Y).
Entering dates
Any day is entered resp. displayed as follows:
This is what you see in FIX 6 display mode. You may also use ALL, but since trailing zeroes are ommited, dates like 1 Jul 1980 will appear as 1,07198 or 15 Aug 2000 will be displayed as 15.082.
The program uses Flag 0 - please see below at the section on using a proleptic Julian calendar.
The following examples assume that Flag 0 is cleared.
Date calculations
The program converts dates both from and to Julian day numbers (JDNs). Any integer input is considered a JDN, and everything with a fractional part is assumed to be a date in dd.mmyyyy format. The program returns two results: the JDN resp. date in X as well as the corresponding weekday in Y. Here 1 = Monday ... 7 = Sunday.
So the general usage is as follows:
Examples
Determine the weekday and Julian day number of 4 July 1979
Now add 1000 days to this...
...and convert back to day, month and year:
How many days have elapsed between 1 Jan 1900 and 31 Dec 1999?
Some useful application samples
Of course you can also add a few little routines that do these calculations for you. For instance here is a DAYS+ routine that adds a number of days to a given date:
Or use another short routine that calculates the difference between two dates:
And finally, the following routine determines the day number within a year (many thanks to Wolfgang for the idea of adding this :-)):
Forcing a proleptic Julian calendar
Unless flag 0 is set, the program assumes that the Julian calendar was used until 4 Oct 1582 as stated in Inter gravissimas by Gregory XIII. Using this date for the switch from Julian to Gregorian is common practice. However, many regions in the world changed later, some not before the 20th century.
Setting Flag 0 now enables a proleptic Julian calendar, i.e. it assumes this calendar was valid for any given date. This allows some useful applications.
1. Converting between Julian and Gregorian calendar
The October Revolution started on 7 Nov 1917. What date was this in the Julian calender used those days in Russia?
Johann Sebastian Bach was born on 21 March 1685 according to the Julian calendar which was still valid in his region. Later the Gregorian calendar was adopted. On which day may Bach have celebrated his birthday after the switch?
2. Adjusting the transition between Julian and Gregorian calendar
The original program assumes the Julian calendar was valid until Thu 4 Oct 1582 which was directly followed by Fri 15 Oct 1582 as the first day of the Gregorian calendar. This is hardcoded by the constant 2299160 in line J040 and J072. It is the JDN of the last day of the Julian calendar, i.e. the JDN of 4 Oct 1582.
If you live in a region where the Gregorian calendar was adopted later, you may want to reflect your local situation by using a different transition point. For instance, Britain and its colonies (including the US) switched after 2 Sep 1752 (followed by 14 Sep 1752). Adjusting the program accordingly is easy:
Now you can replace the constant 2299160 in line J040 and J072 with 2361221 and the transition will occur on 2/14 Sep 1752. After the change you will get the following results:
Now try an undefined date between these two:
Using the unmodified program, you can try the same with 4 Oct 1582 (adding a day will yield 15 Oct 1582) and an invalid date like 10 Oct 1582 (will return 2299156 and 2299166).
Checking dates
The program does not perform any checks to make sure the user entered a valid date, i.e. you may enter 35 Mar 1975 without an error message although March has only 31 days. In this case the program will return the JDN for 4 Apr 1975. This can be used for a simple validity test: simply convert a date to its JDN and back again. If the result matches the original entry, the date was valid.
As usual, any comments, suggestions and corrections are welcome. ;-)
Dieter
- Determining the weekday for a given date
- Calculating the difference between two dates in days
- Adding/subtracting a number of days to/from a given date
- Checking dates for validity
You can now imagine that JDNs make date related calculations very easy - as they are plain integers you can use simple addition and subtraction. Dividing a JDN by 7 yields a remainder that stands for the weekday of that date. Here is a program that does all this. Just to be sure: of course RPN mode is assumed. And be sure not to confuse x<>y (exchange stack registers x and y) and x<> Y (exchange x and variable Y).
Code:
J001 LBL J
J002 IP
J003 LASTx
J004 x=y?
J005 GTO J068
J006 FP // date to JDN
J007 100
J008 x
J009 IP
J010 LASTx
J011 FP
J012 1E4
J013 x
J014 IP
J015 STO Y
J016 R↓
J017 ABS
J018 3
J019 x≤y?
J020 GTO J026
J021 +
J022 9
J023 +
J024 1
J025 STO- Y
J026 SGN
J027 +
J028 30,6
J029 x
J030 IP
J031 x<>y
J032 ABS
J033 +
J034 365,25
J035 RCLx Y
J036 INTG
J037 +
J038 1720995
J039 +
J040 2299160
J041 x<>y
J042 x>y?
J043 FS? 0
J044 GTO J060
J045 ENTER
J046 x<> Y
J047 100
J048 INT÷
J049 -
J050 LASTx
J051 4
J052 INT÷
J053 +
J054 2
J055 +
J056 x>y?
J057 GTO J060
J058 RCL Y
J059 GTO J999
J060 ENTER
J061 ENTER
J062 7
J063 RMDR
J064 1
J065 +
J066 x<>y
J067 RTN
J068 STO X // JDN to date
J069 7
J070 RMDR
J071 x<> X
J072 2299160
J073 x<>y
J074 x>y?
J075 FS? 0
J076 GTO J090
J077 1
J078 +
J079 ENTER
J080 ENTER
J081 1867217,25
J082 -
J083 36524,25
J084 INT÷
J085 +
J086 LASTx
J087 4
J088 INT÷
J089 -
J090 1524
J091 +
J092 ENTER
J093 ENTER
J094 122,1
J095 -
J096 365,25
J097 INT÷
J098 STO Y
J099 LASTx
J100 x
J101 IP
J102 -
J103 ENTER
J104 ENTER
J105 30,6001
J106 INT÷
J107 LASTx
J108 x<>y
J109 ENTER
J110 R↓
J111 x
J112 IP
J113 -
J114 x<>y
J115 1
J116 STO+ X
J117 -
J118 12
J119 x≥y?
J120 GTO J124
J121 -
J122 1
J123 STO+ Y
J124 R↓
J125 100
J126 ÷
J127 +
J128 -4716
J129 RCL+ Y
J130 STO Y
J131 ABS
J132 1E6
J133 ÷
J134 +
J135 RCL Y
J136 x=0?
J137 e^x
J138 SGN
J139 x
J140 RCL X
J141 x<>y
J142 RTN
Variables:
X used
Y used
Flags:
0 set: force (proleptic) Julian calendar
clear: automatic Jul./Greg. switch at 4/15 Oct 1582
Entering dates
Any day is entered resp. displayed as follows:
- All dates are given in dd.mmyyyy format, i.e. 25 December 2014 is 25,122014.
- The useable date range is 1 Jan 4713 BC = –1,014712 to 31 Dec 9999 = 31,129999, which corresponds to JDN 0 to 5373484.
- There was no year 0 (1 BC was followed by 1 AD). The program uses astronomical year numbering, so BC dates differ by one in terms of the year number: 753 BC is year –752.
- The program does not check for validity. But see below for a simple way to do this.
Code:
25 Dec 2014 <=> 25,122014
4 Jul 1979 <=> 4,071979
1 Aug 350 B.C. <=> -1,080349
This is what you see in FIX 6 display mode. You may also use ALL, but since trailing zeroes are ommited, dates like 1 Jul 1980 will appear as 1,07198 or 15 Aug 2000 will be displayed as 15.082.
The program uses Flag 0 - please see below at the section on using a proleptic Julian calendar.
The following examples assume that Flag 0 is cleared.
Date calculations
The program converts dates both from and to Julian day numbers (JDNs). Any integer input is considered a JDN, and everything with a fractional part is assumed to be a date in dd.mmyyyy format. The program returns two results: the JDN resp. date in X as well as the corresponding weekday in Y. Here 1 = Monday ... 7 = Sunday.
So the general usage is as follows:
Code:
input keys output
----------------------------------------------------
dd.mmyyyy [XEQ] J [ENTER] Y: weekday
X: Julian day number
JDN [XEQ] J [ENTER] Y: weekday
X: dd.mmyyyy
----------------------------------------------------
Examples
Determine the weekday and Julian day number of 4 July 1979
Code:
4,071979 [XEQ] J [ENTER] 3 // Wednesday
2444059 // Julian day number of 4 Jul 1979
Now add 1000 days to this...
Code:
1000 [+] 2445059 // JDN 1000 days later
...and convert back to day, month and year:
Code:
[XEQ] J [ENTER] 2 // Tuesday
30,031982 // 30 Mar 1982
How many days have elapsed between 1 Jan 1900 and 31 Dec 1999?
Code:
1,011900 [XEQ] J [ENTER] 1 // Monday
2415021 // JDN
[STO] A // save result
31,121999 [XEQ] J [ENTER] 5 // Friday
2451544 // JDN
[RCL] A [-] // subtract first JDN
36523 // result: 36523 days
Some useful application samples
Of course you can also add a few little routines that do these calculations for you. For instance here is a DAYS+ routine that adds a number of days to a given date:
Code:
A001 LBL A
A002 IP
A003 STO A
A004 x<>y
A005 XEQ J001
A006 RCL+ A
A007 GTO J001
4,071979 [ENTER] // 4 Jul 1979 plus 1000 days
1000 [XEQ] A [ENTER] 2 // is Tuesday,
30,031982 // 30 Mar 1982
Or use another short routine that calculates the difference between two dates:
Code:
D001 LBL D
D002 STO A
D003 x<>y
D004 XEQ J001
D005 x<> A
D006 XEQ J001
D007 RCL- A
D008 RTN
1,011900 [ENTER] // difference between 1 Jan 1900 and 31 Dec 1999
31,121999 [XEQ] D [ENTER] 5 // 31 Dec 1999 was a Friday
36523 // and 36523 days after 1 Jan 1900
And finally, the following routine determines the day number within a year (many thanks to Wolfgang for the idea of adding this :-)):
Code:
N001 LBL N
N002 STO A
N003 100
N004 x
N005 FP
N006 1
N007 +
N008 100
N009 ÷ // build 00.01yyyy
N010 XEQ J001
N011 x<> A
N012 XEQ J001
N013 RCL- A
N014 RTN
23,081999 [XEQ] N [ENTER] 1 // 23 Aug 1999 was a Monday
235 // and the 235th day of the year
Forcing a proleptic Julian calendar
Unless flag 0 is set, the program assumes that the Julian calendar was used until 4 Oct 1582 as stated in Inter gravissimas by Gregory XIII. Using this date for the switch from Julian to Gregorian is common practice. However, many regions in the world changed later, some not before the 20th century.
Setting Flag 0 now enables a proleptic Julian calendar, i.e. it assumes this calendar was valid for any given date. This allows some useful applications.
1. Converting between Julian and Gregorian calendar
The October Revolution started on 7 Nov 1917. What date was this in the Julian calender used those days in Russia?
Code:
[FLAGS] [CF] 0 // just to be sure (date is Gregorian)
7,111917 [XEQ] J [ENTER] 3 // Wednesday
2421540 // JDN
[FLAGS] [SF] 0 // switch to Julian calendar
[XEQ] J [ENTER] 3 // Wednesday
25,101917 // Julian calendar date was 25 Oct 1917
// that's why it's called the October Revolution
Johann Sebastian Bach was born on 21 March 1685 according to the Julian calendar which was still valid in his region. Later the Gregorian calendar was adopted. On which day may Bach have celebrated his birthday after the switch?
Code:
[FLAGS] [SF] 0 // assume Julian calendar
21,031685 [XEQ] J [ENTER] 6 // Saturday
2336584 // JDN
[FLAGS] [CF] 0 // switch back to Gregorian calendar
[XEQ] J [ENTER] 6 // Saturday
31,031685 // According to the Gregorian calendar
// Bach was born on 31 March 1685
2. Adjusting the transition between Julian and Gregorian calendar
The original program assumes the Julian calendar was valid until Thu 4 Oct 1582 which was directly followed by Fri 15 Oct 1582 as the first day of the Gregorian calendar. This is hardcoded by the constant 2299160 in line J040 and J072. It is the JDN of the last day of the Julian calendar, i.e. the JDN of 4 Oct 1582.
If you live in a region where the Gregorian calendar was adopted later, you may want to reflect your local situation by using a different transition point. For instance, Britain and its colonies (including the US) switched after 2 Sep 1752 (followed by 14 Sep 1752). Adjusting the program accordingly is easy:
Code:
[FLAGS] [SF] 0 // assume Julian calendar
2,091752 [XEQ] J [ENTER] 3 // Wednesday
2361221 // JDN
Now you can replace the constant 2299160 in line J040 and J072 with 2361221 and the transition will occur on 2/14 Sep 1752. After the change you will get the following results:
Code:
[FLAGS] [CF] 0 // back to automatic calendar switching
2,091752 [XEQ] J [ENTER] 3 // Wednesday
2361221 // JDN
1 [+] 2361222 // next day
[XEQ] J [ENTER] 4 // was Thursday,
14,091752 // 14 September 1752
Now try an undefined date between these two:
Code:
9,091752 [XEQ] J [ENTER] NONEXISTENT // error: date does not exist
[<-] // clear error message
2361217 // JDN according to Gregorian Calendar
2361228 // JDN according to Julian Calendar
Using the unmodified program, you can try the same with 4 Oct 1582 (adding a day will yield 15 Oct 1582) and an invalid date like 10 Oct 1582 (will return 2299156 and 2299166).
Checking dates
The program does not perform any checks to make sure the user entered a valid date, i.e. you may enter 35 Mar 1975 without an error message although March has only 31 days. In this case the program will return the JDN for 4 Apr 1975. This can be used for a simple validity test: simply convert a date to its JDN and back again. If the result matches the original entry, the date was valid.
Code:
31,091975 [XEQ] J [ENTER] 3 // Wednesday
2442687 // JDN
[XEQ] J [ENTER] 3 // Wednesday
1,101975 // 31 September does not exist
// date is equivalent to 1 October
As usual, any comments, suggestions and corrections are welcome. ;-)
Dieter