-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.Calendar.Persian.Astronomical
-- Copyright   :  (C) 2017 Jason Johnson
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Jason Johnson <jason.johnson.081@gmail.com>
-- Stability   :  experimental
-- Portability :  POSIX, Windows
--
-- Astronomical determination of the Persian (Solar Hijri) new year, Nowruz.  The official Iranian calendar begins each
-- year on the day whose (apparent) noon at the reference meridian (52.5°E, i.e. Iran Standard Time, UTC+3:30) most
-- closely follows the March equinox: Nowruz is the day on which the equinox occurs if it is before true noon in Tehran,
-- otherwise the following day.
--
-- The equinox is computed with the method of Meeus (/Astronomical Algorithms/, ch. 27), corrected to Universal Time with
-- the Espenak–Meeus ΔT polynomials, and compared against true (apparent) noon using the equation of time (Meeus ch. 28).
-- The results are validated against the published modern Nowruz dates and the official leap-year sequence, and against
-- NodaTime's astronomical data (e.g. the epoch 1.Farvardin.1 = 22.Mar.622 CE, and the years where the astronomical and
-- arithmetic calendars diverge).  Accuracy is vouched for over 'minPersianYear' .. 'maxPersianYear'; the functions remain
-- total outside that range but the leap assignment there is an extrapolation.
----------------------------------------------------------------------------
module Data.HodaTime.Calendar.Persian.Astronomical
(
   newYearDay
  ,minPersianYear
  ,maxPersianYear
)
where

import Data.Array.Unboxed (UArray, listArray, (!))

-- | First Persian year the calendar covers (the era begins in 622 CE).
minPersianYear :: Int
minPersianYear :: Int
minPersianYear = Int
1

-- | Last Persian year for which the astronomical calendar is vouched for (≈ 2121 CE).  The equinox and ΔT models are
--   well grounded through this range.
maxPersianYear :: Int
maxPersianYear :: Int
maxPersianYear = Int
1500

-- | The universal flat day (day 0 = 1.Mar.2000 Gregorian, the 'Data.HodaTime.Instant.Instant' epoch) of Nowruz
--   (1 Farvardin) of the given Persian year.  Cached for the supported range and computed on demand outside it, so the
--   calendar is total for every year.
newYearDay :: Int -> Int
newYearDay :: Int -> Int
newYearDay Int
y
  | Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
minPersianYear Bool -> Bool -> Bool
&& Int
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
maxPersianYear Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 = UArray Int Int
cache UArray Int Int -> Int -> Int
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
! Int
y
  | Bool
otherwise                                      = Int -> Int
computeNewYearDay Int
y

-- | Lazy cache of the new-year day for the supported range.  As a CAF it is built once, on the first Persian-calendar
--   operation, and never at all in programs that don't touch the Persian calendar.
cache :: UArray Int Int
cache :: UArray Int Int
cache = (Int, Int) -> [Int] -> UArray Int Int
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [e] -> a i e
listArray (Int
minPersianYear, Int
maxPersianYear Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Int -> Int
computeNewYearDay Int
y | Int
y <- [Int
minPersianYear .. Int
maxPersianYear Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1]]
{-# NOINLINE cache #-}

-- | 1.Mar.2000 Gregorian (the universal flat day 0) as a Julian Day Number.
baseJDN :: Int
baseJDN :: Int
baseJDN = Int -> Int -> Int -> Int
gregorianToJDN Int
2000 Int
3 Int
1

computeNewYearDay :: Int -> Int
computeNewYearDay :: Int -> Int
computeNewYearDay Int
pYear = Int -> Int
nowruzJDN Int
pYear Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
baseJDN

-- | The Julian Day Number of Nowruz for the given Persian year, via the astronomical rule described in the module header.
nowruzJDN :: Int -> Int
nowruzJDN :: Int -> Int
nowruzJDN Int
pYear = if Double
frac Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
threshold then Int
jdn else Int
jdn Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  where
    gregYear :: Int
gregYear = Int
pYear Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
621                              -- Nowruz of Persian year Y falls in Gregorian year Y + 621
    jde :: Double
jde      = Int -> Double
marchEquinoxJDE Int
gregYear                 -- equinox in Terrestrial Time
    jdUT :: Double
jdUT     = Double
jde Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
deltaT Int
gregYear Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
86400            -- convert to Universal Time
    jdTehran :: Double
jdTehran = Double
jdUT Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
3.5 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
24                          -- Iran Standard Time (UTC+3:30, meridian 52.5°E)
    x :: Double
x        = Double
jdTehran Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.5                            -- shift so the integer part is the civil day, 0.5 = noon
    jdn :: Int
jdn      = Double -> Int
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
x :: Int
    frac :: Double
frac     = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
jdn                     -- fraction of the day from midnight (0.5 = mean noon)
    threshold :: Double
threshold = Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
eotDays Double
jde                       -- true (apparent) noon differs from mean noon by the equation of time

-- | The March (northward) equinox as a Julian Ephemeris Day (Terrestrial Time), per Meeus /Astronomical Algorithms/ ch. 27.
marchEquinoxJDE :: Int -> Double
marchEquinoxJDE :: Int -> Double
marchEquinoxJDE Int
year
  | Int
year Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1000 = Double -> Double
correct (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
1721139.29189 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
365242.13740 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.06134 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y1 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.00111 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y1 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.00071 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y1 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
4
  | Bool
otherwise    = Double -> Double
correct (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
2451623.80984 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
365242.37404 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.05169 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.00411 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.00057 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y2 Double -> Double -> Double
forall a. Floating a => a -> a -> a
** Double
4
  where
    y1 :: Double
y1 = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
year Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000
    y2 :: Double
y2 = (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
year Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2000) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1000
    correct :: Double -> Double
correct Double
jde0 = Double
jde0 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
0.00001 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
s) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
dl
      where
        t :: Double
t  = (Double
jde0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2451545.0) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
36525
        w :: Double
w  = Double
35999.373 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2.47
        dl :: Double
dl = Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0334 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double -> Double
d2r Double
w) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0007 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double -> Double
d2r (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
w))
        s :: Double
s  = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Double
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double -> Double
d2r (Double
b Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
c Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t)) | (Double
a, Double
b, Double
c) <- [(Double, Double, Double)]
periodicTerms ]

-- | The 24 periodic terms (A, B, C) of Meeus table 27.C, used to refine the mean equinox.
periodicTerms :: [(Double, Double, Double)]
periodicTerms :: [(Double, Double, Double)]
periodicTerms =
  [ (Double
485, Double
324.96,   Double
1934.136), (Double
203, Double
337.23,  Double
32964.467), (Double
199, Double
342.08,     Double
20.186)
  , (Double
182,  Double
27.85, Double
445267.112), (Double
156,  Double
73.14,  Double
45036.886), (Double
136, Double
171.52,  Double
22518.443)
  , ( Double
77, Double
222.54,  Double
65928.934), ( Double
74, Double
296.72,   Double
3034.906), ( Double
70, Double
243.58,   Double
9037.513)
  , ( Double
58, Double
119.81,  Double
33718.147), ( Double
52, Double
297.17,    Double
150.678), ( Double
50,  Double
21.02,   Double
2281.226)
  , ( Double
45, Double
247.54,  Double
29929.562), ( Double
44, Double
325.15,  Double
31555.956), ( Double
29,  Double
60.93,   Double
4443.417)
  , ( Double
18, Double
155.12,  Double
67555.328), ( Double
17, Double
288.79,   Double
4562.452), ( Double
16, Double
198.04,  Double
62894.029)
  , ( Double
14, Double
199.76,  Double
31436.921), ( Double
12,  Double
95.39,  Double
14577.848), ( Double
12, Double
287.11,  Double
31931.756)
  , ( Double
12, Double
320.81,  Double
34777.259), (  Double
9, Double
227.73,   Double
1222.114), (  Double
8,  Double
15.45,  Double
16859.074)
  ]

-- | ΔT (Terrestrial Time − Universal Time), in seconds, from the Espenak & Meeus polynomial expressions.
deltaT :: Int -> Double
deltaT :: Int -> Double
deltaT Int
yr
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
500   = let u :: Double
u = Double
y Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100         in Double
10583.6 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1014.41 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
u Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
33.78311 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
5.952053 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.1798452 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.022174192 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
5 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0090316521 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
6
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1600  = let u :: Double
u = (Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1000) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100 in Double
1574.2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
556.01 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
u Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
71.23472 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.319781 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.8503463 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.005050998 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
5 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0083572073 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
6
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1700  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1600 in Double
120 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.9808 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.01532 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
7129
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1800  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1700 in Double
8.83 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.1603 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0059285 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.00013336 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
tDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1174000
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1860  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1800 in Double
13.72 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.332447 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0068612 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0041116 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.00037436 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0000121272 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
5 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0000001699 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
6 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.000000000875 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
7
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1900  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1860 in Double
7.62 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.5737 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.251754 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.01680668 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0004473624 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
tDouble -> Int -> Double
^.Int
5 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
233174
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1920  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1900 in -Double
2.79 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.494119 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0598939 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0061966 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.000197 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
4
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1941  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1920 in Double
21.20 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.84493 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.076100 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0020936 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1961  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1950 in Double
29.07 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.407 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
233 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2547
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
1986  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1975 in Double
45.45 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1.067 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
260 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
718
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
2005  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2000 in Double
63.86 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.3345 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.060374 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0017275 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
3 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.000651814 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.00002373599 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
5
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
2050  = let t :: Double
t = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2000 in Double
62.92 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.32217 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.005589 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2
  | Double
y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
2150 = -Double
20 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
32 Double -> Double -> Double
forall a. Num a => a -> a -> a
* ((Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1820) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100)Double -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5628 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
2150 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
y)
  | Bool
otherwise = let u :: Double
u = (Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1820) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
100 in -Double
20 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
32 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
uDouble -> Int -> Double
^.Int
2
  where y :: Double
y = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
yr :: Double

-- | The equation of time (apparent − mean solar time), in days, at the given instant (Meeus ch. 28, low-accuracy form).
eotDays :: Double -> Double
eotDays :: Double -> Double
eotDays Double
jde = Double
bigE Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi)
  where
    t :: Double
t   = (Double
jde Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2451545.0) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
36525
    l0 :: Double
l0  = Double -> Double
d2r (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
280.46646 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
36000.76983 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.0003032 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2
    m :: Double
m   = Double -> Double
d2r (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
357.52911 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
35999.05029 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0001537 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2
    e :: Double
e   = Double
0.016708634 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.000042037 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0000001267 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
tDouble -> Int -> Double
^.Int
2
    eps :: Double
eps = Double -> Double
d2r (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
23.439291 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.0130042 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t
    yy :: Double
yy  = Double -> Double
forall a. Floating a => a -> a
tan (Double
eps Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2) Double -> Int -> Double
^. Int
2
    bigE :: Double
bigE = Double
yy Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
l0) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
e Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
m Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
e Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
yy Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
m Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
l0) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
yyDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin (Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
l0) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1.25 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
eDouble -> Int -> Double
^.Int
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
m)

d2r :: Double -> Double
d2r :: Double -> Double
d2r Double
x = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
180

-- | Integer power with a fixed 'Int' exponent, avoiding the type defaulting of the exponent (which @-Wtype-defaults@
--   would otherwise flag) in the polynomial expressions above.
(^.) :: Double -> Int -> Double
^. :: Double -> Int -> Double
(^.) = Double -> Int -> Double
forall a b. (Num a, Integral b) => a -> b -> a
(^)
infixr 8 ^.

-- | Julian Day Number for a proleptic Gregorian date.
gregorianToJDN :: Int -> Int -> Int -> Int
gregorianToJDN :: Int -> Int -> Int -> Int
gregorianToJDN Int
y Int
m Int
d = Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
153 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
m' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
365 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
y' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
y' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
100 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
400 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
32045
  where
    a :: Int
a  = (Int
14 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
m) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
12
    y' :: Int
y' = Int
y Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
4800 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a
    m' :: Int
m' = Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
12 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3