(35S) calendar and date functions
01-28-2015, 08:24 PM (This post was last modified: 06-15-2017 01:31 PM by Gene.)
Post: #1
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
(35S) calendar and date functions
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:
• 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
The following program works with Julian day numbers (JDNs). As opposed to the familiar notation with day, month and year, JDNs are simple consecutive numbers. Every day has a unique JDN, and 100 days later the JDN has increased by 100 as well - it's as simple as that. The day count starts with day 0 being 1 Jan 4713 B.C., and the last day the program handles is 31 Dec 9999 which is JDN 5373484. The switch from the older Julian to the current Gregorian calender is implemented in that Thu 4 Oct 1582 is directly followed by Fri 15 Oct 1582. You may may change this to a different date, for instance if in your region the switch occured later - see below.

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.
Examples for valid input/output:

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
03-09-2018, 09:55 PM
Post: #2
 Matt Agajanian Senior Member Posts: 495 Joined: Dec 2013
RE: (35S) calendar and date functions
Thanks (as usual), Dieter for such an extensive resource!
03-27-2019, 04:59 PM
Post: #3
 ErikN Junior Member Posts: 3 Joined: Mar 2019
RE: (35S) calendar and date functions
This is a great program!
It's the first program I entered into my new 35s, and it works like a charm. Thank you for sharing!
 « Next Oldest | Next Newest »

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