The main documentation of the Julian_Day Procedure contains additional explanation of this code listing.
function Julian_Day (Year, Month, Day, Calendar, Debug) ! Use association information. use Caesar_Numbers_Module, only: four ! Input variables. type(integer), intent(in) :: Year ! Input year. type(integer), intent(in) :: Month ! Input month. type(integer), intent(in) :: Day ! Input day. type(character,*), intent(in), optional :: Calendar ! Julian or ! Gregorian calendar. type(logical), intent(in), optional :: Debug ! Debug toggle. ! Output variables. type(integer) :: Julian_Day ! Julian Day. ! Internal variables. type(character,9) :: A_Calendar ! Actual calendar. type(logical) :: A_Debug ! Actual debug toggle. type(integer) :: Julian_Day_Constant ! Shift for new zero date. type(integer) :: Julian_Year ! Julian Year (includes zero). type(integer) :: Julian_Month ! Julian Month (4-15). type(integer) :: Shifted_Julian_Year ! Julian Year + 8000. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Set actual debug toggle. if (PRESENT(Debug)) then A_Debug = Debug else A_Debug = .true. end if ! Verify requirements. if (A_Debug) then VERIFY(Valid_State(Year),4) ! Year is valid. VERIFY(Valid_State(Month),4) ! Month is valid. VERIFY(Valid_State(Day),4) ! Day is valid. VERIFY(Year/=0,2) ! Year is non-zero. VERIFY(Month.InInterval.(/1,12/),2) ! Month is between 1 and 12. VERIFY(Day.InInterval.(/1,31/),2) ! Day is between 1 and 31. ! Year is after the first Julian day occurred (1 January 4713 BC). VERIFY(Year >= -4713,4) end if ! More specific requirements on Day (for higher verification levels). if (A_Debug) then if (Month==4 .or. Month==6 .or. Month==9 .or. Month==11) then ! Day is between 1 and 30 for April, June, September and November. VERIFY(Day.InInterval.(/1,30/),6) else if (Month==2) then ! Day is between 1 and 29 for February. VERIFY(Day.InInterval.(/1,29/),6) end if end if ! Set calendar to use. if (PRESENT(Calendar)) then A_Calendar = Calendar else A_Calendar = 'Gregorian' end if ! Further requirements that are dependent on the calendar. if (A_Debug) then if (A_Calendar == 'Gregorian') then ! Warn if year is before Gregorian dates were adopted in the ! first countries in Europe (4 October 1582 CE). IF_NOT_UNIT_TEST WARN_IF(Year < 1582,6) ! Warn if year is before Gregorian dates were adopted in ! England and the American Colonies (14 September 1752 CE). IF_NOT_UNIT_TEST WARN_IF(Year < 1752,8) else if (A_Calendar /= 'Julian') then ! Only Julian and Gregorian calendars allowed. VERIFY(.false.,0) end if end if ! Convert to Julian (CE) Year, which includes a zero year: ! ! BC AD ! Year: -4 -3 -2 -1 1 2 3 4 ! Julian Year: -3 -2 -1 0 1 2 3 4 if (Year > 0) then Julian_Year = Year else Julian_Year = Year + 1 end if ! Convert to Julian Month for ease in calculating month days and ! dealing with February. ! ! Month: 1 2 3 4 5 6 7 8 9 10 11 12 ! Julian Month: 14 15 4 5 6 7 8 9 10 11 12 13 ! ! For consistency, modify Julian_Year to start with March. if (Month < 3) then Julian_Month = Month + 13 Julian_Year = Julian_Year - 1 else Julian_Month = Month + 1 end if ! Calculate Julian_Year shifted by 8000 years to avoid problems ! with leap years in negative years. Shifted_Julian_Year = Julian_Year + 8000 ! Adjustment constant -- this is the number of days from the start ! of the Julian Day numbering system, 1 January 4713 BC, to the new ! zero date which is used for calculations. Due to the month shifting, ! the new zero date is 30 October 2 BC. Julian_Day_Constant = - ( & + 365*(-4713) & ! 365 days/year. + int(30.6001*14) & ! Trick to get days/month. + int((-4713+8000)/4) - 2000 & ! Leap days. + 1 & ! Day of the month. ) ! Calculate Julian Day. if (A_Calendar == 'Julian') then Julian_Day = Julian_Day_Constant & ! Adjustment constant. + 365*(Julian_Year) & ! 365 days/year. + int(30.6001*Julian_Month) & ! Trick to get days/month. + int(Shifted_Julian_Year/4) - 2000 & ! Leap days. + Day ! Day of the month. else if (A_Calendar == 'Gregorian') then Julian_Day = Julian_Day_Constant & ! Adjustment constant. + 365*Julian_Year & ! 365 days/year. + int(30.6001*Julian_Month) & ! Trick to get days/month. + int(Shifted_Julian_Year/4) - 2000 & ! Leap days. - int(Shifted_Julian_Year/100) + 80 & ! Gregorian leap + int(Shifted_Julian_Year/400) - 20 & ! day adjustment. + 2 & ! Difference between ! Gregorian and Julian ! calendars at 0 CE. + Day ! Day of the month. end if ! Verify guarantees. if (A_Debug) then VERIFY(Valid_State(Julian_Day),4) ! Julian_Day is valid. VERIFY(Julian_Day >= 0,4) ! Julian_Day is non-negative. end if return end function Julian_Day