Post Reply 
A tiny New Year's programming challenge
01-22-2015, 01:50 PM
Post: #22
RE: A tiny New Year's programming challenge
I suppose, I'm a bit late for a "New Year's" programming challenge, but I want to contribute a HP-16C program to convert calender date representations.

My solution uses a subroutine to convert a (proleptic) Gregorian Calender date YYYY-MM-DD to a Julian Day Number (i.e. the Julian Date as of YYYY-MM-DDT12:00Z).
Code:

43,22,D     g LBL D     x=yyyy, y=mm, z=dd
34          x<->y       x=mm, y=yyyy, z=dd
3           [3]
30          -           m = mm-3
43,2        g x<0       m < 3 ?
21,0        GSB 0       => m = mm+12, y = yyyy-1
1           [1]
5           [5]
3           [3]
20          x   
2           [2]
40          +
5           [5]
10          ./.         x=(153m+2)/5, y=y, z=d, t=?
34          x<->y       x=y, y=(153m+2)/5, z=d, t=?
33          Rv          x=(153m+2)/5, y=d, z=?, t=y
40          +           x=(153m+2)/5+d, y=?, z=y, t=y
3           [3]
6           [6]
5           [5]
43,33       g R^        x=y, y=365, z=(153m+2)/5+d, t=?
20          x
43,36       g LSTx      x=y, y=365*y, z=(153m+2)/5+d, t=?
4           [4]
10          ./.         x=y/4, y=365*y, z=(153m+2)/5+d, t=?
40          +
43,36       g LSTx      x=y/4, y=365*y+y/4, z=(153m+2)/5+d, t=?
2           [2]
5           [5]
10          ./.         x=y/100, y=365*y+y/4, z=(153m+2)/5+d, t=?
30          -
43,36       g LSTx      x=y/100, y=365*y+y/4-y/100, z=(153m+2)/5+d, t=?
4           [4]
10          ./.         x=y/400, y=365*y+y/4-y/100, z=(153m+2)/5+d, t=?
40          +
40          +           x=d+(153m+2)/5+365*y+y/4-y/100+y/400
1           [1]
7           [7]
2           [2]
1           [1]
1           [1]
1           [1]
9           [9]
40          +           adjust for JD
43,21       g RTN

43,22,0     g LBL 0     x=mm-3, y=yyyy, z=dd
1           [1]
2           [2]
40          +   
34          x<->y
1           [1]
30          -
34          x<->y
43,21       g RTN       x=mm+12 y=yyyy-1

ISO 8601 calender date representations:
  • Calendar date: YYYY-MM-DD
    where YYYY represents a calendar year, MM the ordinal number of a calendar month within the calendar year, and DD the ordinal number of a calendar day within the calendar month
  • Ordinal date: YYYY-DDD
    where YYYY represents a calendar year and DDD the ordinal number of a calendar day within the calendar year
  • Week date: YYY-Www-D
    where YYYY represents a calendar year, W is the week designator, ww represents the ordinal number of a calendar week within the year, and D represents the ordinal number of a calendar day within the calendar week.

Convert calendar date to ordinal date or week date using the Julian Day Number JDN(YYYY-MM-DD).
  • Julian Day Number
    if mm > 2 then m := mm-3; y:=yyyy else m := mm+12; y := yyyy-1 endif
    JDN(yyyy-mm-dd) := 365*y + y/4 - y/100 + y/400 + (153*m+2)/5 + dd + 1721119
  • Ordinal number of a calendar day within the calendar week (Calendar day of the week, CDW)
    CDW = (JDN(yyyy-mm-dd) mod 7) + 1
  • Ordinal number of a calendar day within the calendar year (Calender day of the year, CDY)
    CDY = JDN(yyyy-mm-dd) - JDN(yyyy-01-01)
  • Ordinal number of a calendar week within the year (Calender week, CW)
    CW = [(CDY - CDW + 10) / 7]
    The expression (CDY-CDW+10) is constant for a calender week (1 <= CDW <= 7) and increments by 7 for the next week.
    For CW = 1 there is 7 <= (CDY - CDW + 10) <= 13
    For CDY = 1 (1st of January): If CW = 1 then CDW <= 4 (Thursday)
    Special cases:
    • (CDY - CDW + 10) / 7 == 0:
      the calendar day belongs to calendar week 52 or 53 of the preceding year.
      CW = 53 if the 1st of January of the preceding year is in calendar week 1 of the preceding year i.e. is Monday to Thursday, otherweise CW = 52.
    • (CDY - CDW + 10) / 7 == 53:
      the calendar day belongs to calendar week 1 of the next year, if the 1st of January of the next year is Tuesday to Thurday. Otherwise it is really CW 53.
Code:

43,22,C     g LBL C
44,0        STO 0       calendar year for ordinal date (YYYY-DDD)
44,5        STO 5       calender year for week date (YYYY-Www-D)
21,d        GSB D       compute Julian Day Number
44,4        STO 4
7           [7]         compute day of week
42,9        f RMD       CDW = (JDN mod 7) + 1
1           [1]    
40          +
44,3        STO 3
1           [1]
36          ENTER
36          ENTER
45,0        RCL 0
21,d        GSB D       compute Julian Date of 1st of January
45,4        RCL 4       compute day of year
34          x<->y       CDY = JDN(yyyy-mm-dd) - JDN(yyyy-01-01) + 1
30          -
1           [1]
40          +
44,1        STO 1       
45,3        RCL 3       compute week number 
30          -           CW = (CDY - CDW + 10) / 7
1           [1]
0           [0]
+           +
7           [7]
10          ./.
44,2        STO 2
43,30       g x>0       special calculation for CW=0?
22,1        GTO 1       No, check for CW 53
5           [5]
2           [2]
44,2        STO 2       assume CW =52
43,4,2      g SF 2      compute Calender Day of the Week
21,2        GSB 2       for the 1st of January of the preceding year
3           [3]
43,3        g x>y       if (YYYY-1)-01-01 > Thursday 
22,0        GTO 0       then CDW := 52; YYYY := YYYY-1;
5           [5]         else CDW := 53; YYYY := YYYY-1;
3           [3]
44,2        STO 2
22,0        GTO 0
43,22,1     g LBL 1
5           [5]
3           [3]
43,0        g x<>y      special calculation for CW=53?
22,0        GTO 0       No, display result
43,5,2      g CF 2      compute Calender Day of the Week
21,2        GSB 2       for the 1st of January of the next year
3           [3]
34          x<->y
43,3        g x>y       if (YYYY+1)-01-01 < Thursday
22,0        GTO 0       then CW := 53;
1           [1]         else CW := 1; YYYY := YYYY+1;
44,2        STO 2
45,0        RCL 0
40          + 
44,0        STO 5       
43,22,0     g LBL 0     show results
45,0        RCL 0       calendar year (YYYY)
1           [1]
0           [0]
0           [0]
0           [0]
20          x           (YYYY000)
45,1        RCL 1       Calender Day of the Year (1...365/366)
40          +           ISO 8601 ordinal date: YYYYDDD
45,3        RCL 3       Calender day of the Week (1=Mon,...,7=Sun)
45,2        RCL 2       Calender Week of the Year (1..52/53)
45,5        RCL 5       Calender Year (corrected for Calender Week)
43,21       g RTN
            
43,22,2     g LBL 2     Compute Calender Day of Week for the 1st of January
1           [1]         of the preceding year (flag 2 set)
36          ENTER       or the next year (flag 2 cleared)
36          ENTER       
43,6,2      g F? 2
49          CHS
45,0        RCL 0       x = YYYY
40          +           x = (Flag 2 set) ? YYYY-1 : YYYY+1
43,6,2      g F? 2
44,0        STO 5       Store YYYY-1
21,d        GSB D       JDN(x-01-01)
7           [7]
42,9        f RMD       CDW (0=Mon,...,3=Thu,...,6=Sun)
43,21       g RTN

Registers:
R0 = calendar year (YYYY)
R1 = calendar day of the year (DDD)
R2 = calendar week (ww)
R3 = calendar day of the week (D)
R4 = julian day number
R5 = calendar year for week date (R0+-1)

Usage:
DEC
{DD}
ENTER
{MM}
ENTER
{YYYY}
GSB C

Display result:
YYYY (corrected for calender week)
Rdown
ww (calender week: 1-53)
Rdown
D (weekday (1=Mon,...,7=Sun)
Rdown
YYYYDDD (ISO 8601 ordinal date)

Comments are welcome

Hartmut
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: A tiny New Year's programming challenge - wynen - 01-22-2015 01:50 PM



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