content: -- #hide
  module Data.Time.Calendar.JulianYearDay
  	(
  	-- * Year and day format
  	module Data.Time.Calendar.JulianYearDay
  	) where
  
  import Data.Time.Calendar.Days
  import Data.Time.Calendar.Private
  
  -- | convert to proleptic Julian year and day format. First element of result is year (proleptic Julian calendar),
  -- second is the day of the year, with 1 for Jan 1, and 365 (or 366 in leap years) for Dec 31.
  toJulianYearAndDay :: Day -> (Integer,Int)
  toJulianYearAndDay (ModifiedJulianDay mjd) = (year,yd) where
  	a = mjd + 678577
  	quad = div a 1461
  	d = mod a 1461
  	y = min (div d 365) 3
  	yd = fromInteger (d - (y * 365) + 1)
  	year = quad * 4 + y + 1
  
  -- | convert from proleptic Julian year and day format.
  -- Invalid day numbers will be clipped to the correct range (1 to 365 or 366).
  fromJulianYearAndDay :: Integer -> Int -> Day
  fromJulianYearAndDay year day = ModifiedJulianDay mjd where
  	y = year - 1
  	mjd = (fromIntegral (clip 1 (if isJulianLeapYear year then 366 else 365) day)) + (365 * y) + (div y 4) - 678578
  
  -- | convert from proleptic Julian year and day format.
  -- Invalid day numbers will return Nothing
  fromJulianYearAndDayValid :: Integer -> Int -> Maybe Day
  fromJulianYearAndDayValid year day = do
  	day' <- clipValid 1 (if isJulianLeapYear year then 366 else 365) day
  	let
  		y = year - 1
  		mjd = (fromIntegral day') + (365 * y) + (div y 4) - 678578
  	return (ModifiedJulianDay mjd)
  
  -- | show in proleptic Julian year and day format (yyyy-ddd)
  showJulianYearAndDay :: Day -> String
  showJulianYearAndDay date = (show4 (Just '0') y) ++ "-" ++ (show3 (Just '0') d) where
  	(y,d) = toJulianYearAndDay date
  
  -- | Is this year a leap year according to the proleptic Julian calendar?
  isJulianLeapYear :: Integer -> Bool
  isJulianLeapYear year = (mod year 4 == 0)
  