'===========================================================================
' Subject: What is the Julian Date?           Date: 06-16-02 (  :  )       
'  Author: David Williams                     Code: Qbasic,QB,PDS          
'  Origin: david.williams@ablelink.org      Packet: DATETIME.ABC
'===========================================================================
'There are already some programs of mine in the ABC archives. Maybe this
'one should go there too. People who are interested in astronomy may
'well find it useful.
  
'David Williams
  
'-------------------------------------------------
  
' JGCONV.BAS
' Julian Day and Gregorian Date interconverter
  
' David Williams. 2001
' david.williams@ablelink.org
  
' Program interconverts Gregorian-calendar dates (regular ones)
' with Julian Days, a dating system used by astronomers which
' simply counts days from a starting point in the distant past.
  
' Note: For years before 1 C.E. (A.D.), program uses rationalized
' calendar. Year before year 1 is year 0. Year before that is
' year -1, and so on.
  
DECLARE SUB J2G ()
DECLARE SUB G2J ()
DECLARE SUB JultoGreg ()
DECLARE SUB GregtoJul ()
DECLARE FUNCTION Dte$ ()
DECLARE FUNCTION DivMult% (FirstPeriod%, LastPeriod%)
  
DEFINT A-Z
DIM SHARED Year AS INTEGER, Month AS INTEGER, Day AS SINGLE
DIM SHARED JulianDay AS DOUBLE, Num AS DOUBLE
DIM SHARED Period(1 TO 7, 1 TO 2) AS LONG
  
CONST ZeroOffset# = 1721119.5#
' Difference between Julian and Gregorian zeroes.
' Note: Julian Days start and end at noon UT, hence the .5
  
DATA 146097, 400, 36524, 100, 1461, 4, 365, 1, 153, 5, 61, 2, 31, 1
'Data are day-numbers and periods, e.g. 146097 days in 400 years.
'First 4 pairs are days and years. Last 3 are days and months.
  
FOR X = 1 TO 7
  FOR Y = 1 TO 2
    READ Period(X, Y)
  NEXT
NEXT
  
CLS
PRINT "Decimal fractions of Julian Days or Days of Month are allowed."
PRINT "Gregorian Dates should be in Universal Time (GMT)."
  
DO
  PRINT
  PRINT "1.  Gregorian to Julian"
  PRINT "2.  Julian to Gregorian"
  PRINT "3.  Quit"
  PRINT
  PRINT "Which? (by number) ";
  
  DO
    Key$ = INKEY$
  LOOP UNTIL Key$ >= "1" AND Key$ <= "3"
  PRINT Key$
  PRINT
  
  SELECT CASE Key$
     CASE "1"
       CALL G2J
     CASE "2"
       CALL J2G
     CASE "3"
       EXIT DO
  END SELECT
  
LOOP
  
END
  

FUNCTION DivMult (FirstPeriod, LastPeriod)
' Utility function used by JultoGreg
  
 Total = 0
  
 FOR J = FirstPeriod TO LastPeriod
  
   Quot = INT(Num / Period(J, 1))' number of periods in Num days
  
   IF Quot = 4 THEN
      IF J = 2 OR J = 4 THEN Quot = 3' needed for February 29
   END IF
  
   Num = Num - Quot * Period(J, 1)' subtract the periods from Num
  
   Total = Total + Quot * Period(J, 2)' add in the years or months
  
 NEXT J
  
 DivMult = Total' number of years or months
  
END FUNCTION

FUNCTION Dte$ ' puts Gregorian date in standard format
  
  Dte$ = STR$(Year) + "," + STR$(Month) + "," + STR$(Day)
  
END FUNCTION

SUB EaSun (Year, Month, Day) ' Finds month and day of Easter Sunday
  
  J = Year MOD 19
  K = Year \ 100
  L = Year MOD 100
  M = K \ 4
  N = K MOD 4
  O = L \ 4
  P = L MOD 4
  Q = (8 * K + 13) \ 25
  R = (19 * J + K - M - Q + 15) MOD 30
  S = (J + 11 * R) \ 319
  T = (2 * (N + O) - P - R + S + 32) MOD 7
  U = R - S + T
  
  Month = (U + 90) \ 25
  Day = (U + Month + 19) MOD 32
  
END SUB

SUB G2J ' Gregorian to Julian package
  
  INPUT "Greg. Date (YYYY,MM,DD) (WITH commas!) "; Year, Month, Day
  
  Date1$ = Dte$
  
  CALL GregtoJul
  CALL JultoGreg' Reverse conversion checks date's legality
  
  IF Date1$ = Dte$ THEN
         PRINT
         PRINT "Julian Day is: "; JulianDay
  ELSE
         BEEP
         PRINT
         PRINT "Illegal Gregorian Date"
  END IF
  
END SUB

SUB GregtoJul ' Does basic Gregorian to Julian conversion
  
  ' Shift New Year from January 1 to March 1
  IF Month < 3 THEN
      Mth = Month + 9
      Yr = Year - 1
  ELSE
      Mth = Month - 3
      Yr = Year
  END IF
  
  Leap = INT(Yr / 4) - INT(Yr / 100) + INT(Yr / 400)
  ' leap years since Gregorian zero (March 1 in Year 0)
  
  Before = INT(30.6 * Mth + .5)
  ' days in this year (starting March 1) before present month
  
  JulianDay = ZeroOffset# + 365& * Yr + Leap + Before + Day - 1
  
END SUB

SUB J2G ' Julian to Gregorian package
  
  INPUT "Julian Day"; JulianDay
  
  CALL JultoGreg
  
  PRINT
  PRINT "In format Year, Month, Day: Gregorian Date is:  "; Dte$
  
END SUB

SUB JultoGreg ' Does basic Julian to Gregorian conversion
  
  Num = JulianDay - ZeroOffset#' days since Gregorian zero
  ' Note: DivMult reduces Num to show days remaining.
  
  Yr = DivMult(1, 4)' periods 1 - 4 are multiples of years
  
  Mth = DivMult(5, 7)' periods 5 - 7 are multiples of months
  
  Day = Num + 1' first day of month is #1, not #0
  
  ' Shift New Year from March 1 to January 1
  IF Mth > 9 THEN
      Month = Mth - 9
      Year = Yr + 1
  ELSE
      Month = Mth + 3
      Year = Yr
  END IF
  
END SUB

