[comp.lang.asm370] Table-less Gregorian Date Conversion

CAREY@CLEMSON.BITNET (Jim Blalock) (01/05/90)

(Maybe this will go to the right list this time.  That's what I get
for not using the REPLY command :-)

Since everyone's so interested in date conversion these days...

The following rexx procedure is a modified version of algorithm 199
from ACM's "Collected Algorithms". (This is not the same as the
'tableless date conversion' posted recently.)  Procedure JDAY converts
a Gregorian date into the number of days since Jan. 1, 0000 (same as
rexx's "basedate" format), while procedure JDATE converts it back.
(The original adds 1721119 to the basedate, creating a "real" Julian
date of number-of-days-since-approx-4700-BC.)  The algorithm claims to
work for any valid (positive!) Gregorian date.

/*  rexx  */

  Do Forever      /* dumb driver to call the procedures */
    say "Enter Gregorian date to convert, or END to terminate test."
    valid = DUNNO
    do while valid ^= TRUE
      if valid = FALSE then do
        say "Invalid Gregorian date, use format ""mm/dd/yyyy""."
      end
      pull answer
      if answer = 'END' then exit
      parse var answer m "/" d "/" y
      if datatype(d) = "NUM" & datatype(m) = "NUM" ,
          & datatype(y) = "NUM" ,
        then valid = TRUE
      else valid = FALSE
    end
    j = JDAY(m,d,y)
    say "  Converted date value = " j "."
    gdate = JDATE(j)
    say "  Restored date value is: " gdate "."
  End

  exit

JDAY: procedure
  parse upper arg m, d, y
  if m > 2 then m = m - 3
  else do
    m = m + 9
    y = y - 1
  end
  c = y % 100
  ya = y - (100 * c)
  j = (146097 * c) % 4 + (1461 * ya) % 4 + ((153 * m) + 2) % 5 + d
  return (j)

JDATE: procedure
  parse upper arg j
  y = ((4 * j) - 1) % 146097
  j = ((4 * j) - 1) - (146097 * y)
  d = j % 4
  j = ((4 * d) + 3) % 1461
  d = ((4 * d) + 3) - (1461 * j)
  d = (d + 4) % 4
  m = ((5 * d) - 3) % 153
  d = ((5 * d) - 3) - (153 * m)
  d = (d + 5) % 5
  y = (100 * y) + j
  if m < 10 then m = m + 3
  else do
    m = m - 9
    y = y + 1
  end
  gdate = m || "/" d || "/" || y
  return (gdate)