horizon (empty) → 0.1.0
raw patch · 5 files changed
+198/−0 lines, 5 filesdep +AC-Angledep +basedep +timesetup-changed
Dependencies added: AC-Angle, base, time
Files
- LICENSE +30/−0
- README.org +11/−0
- Setup.hs +2/−0
- horizon.cabal +31/−0
- src/Data/Time/Horizon.hs +124/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Joel Stanley++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Joel Stanley nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.org view
@@ -0,0 +1,11 @@+* Welcome!++ This package contains a Haskell module for computing approximate sunrise and+ sunset UTC times from latitude and longitude.++ Note that approximations are provided in UTC time only, no additional support+ for time zones is implemented.++ This module has only been lightly tested, and produces values close to those+ found at http://aa.usno.navy.mil/data/docs/RS_OneYear.php.+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ horizon.cabal view
@@ -0,0 +1,31 @@+name: horizon+version: 0.1.0+synopsis: Sunrise and sunset UTC approximations from latitude and longitude coordinates+description: Provides a basic implementation of the sunrise and sunset equations from <https://en.wikipedia.org/wiki/Sunrise_equation this wikipedia page>.+license: BSD3+license-file: LICENSE+author: Joel Stanley+maintainer: intractable@gmail.com+category: Data+build-type: Simple+extra-source-files: README.org+cabal-version: >=1.10+stability: provisional+homepage: https://github.com/intractable/horizon+bug-reports: https://github.com/intractable/horizon/issues+Package-url: http://hackage.haskell.org/package/horizon+tested-with: GHC == 7.8.3 ++library+ exposed-modules: Data.Time.Horizon+ -- other-modules:+ -- other-extensions:+ build-depends: base >=4.7 && < 4.8,+ time >= 1.4.2 && < 1.5,+ AC-Angle >= 1.0 && < 2.0+ hs-source-dirs: src+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/intractable/horizon.git
+ src/Data/Time/Horizon.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE ViewPatterns #-}++{-+ Module : Data.Time.Horizon+ License : BSD3+ Copyright : (C) 2015 Joel Stanley+ Maintainer : Joel Stanley <intractable@gmail.com>+ Stability : provisional+ + Provides approximate sunrise and sunset times in UTC from latitude and + longitude coordinates.++ See https://en.wikipedia.org/wiki/Sunrise_equation.+ See http://aa.usno.navy.mil/data/docs/RS_OneYear.php.++-}++module Data.Time.Horizon+ ( LatitudeNorth+ , LongitudeWest+ , sunrise+ , sunset+ )+ where++import Data.Angle+import Data.Fixed+import Data.Time++type LatitudeNorth = Double +type LongitudeWest = Double++-- | Returns an approximated UTC time of the sunrise on the given UTC day at the given location.+sunrise :: Day -> LongitudeWest -> LatitudeNorth -> UTCTime+sunrise d lw ln = mkUTC d . jdToSeconds $ sunrise' d lw ln++-- | Returns an approximated UTC time of the sunset on the given UTC day at the given location.+sunset :: Day -> LongitudeWest -> LatitudeNorth -> UTCTime+sunset d lw ln = mkUTC d . jdToSeconds $ sunset' d lw ln++-- | Approximate the Julian date of the sunrise on the given UTC day at the given location.+sunrise' :: Day -> LongitudeWest -> LatitudeNorth -> Double+sunrise' d lw ln = jtransit - (jset - jtransit)+ where+ u = mkUTC d 0+ jtransit = solarTransit u lw+ jset = sunset' d lw ln++-- | Approximate the Julian date of the sunset on the given UTC day at the given location.+sunset' :: Day -> LongitudeWest -> LatitudeNorth -> Double+sunset' d lw ln =+ 2451545.0009 + ((w0 + lw) / 360) + n + 0.0053 * sine m - 0.0069 * sine (2 * lambda)+ where+ u = mkUTC d 0+ Degrees w0 = omega0 u lw ln+ n = fromIntegral (julianCycle u lw :: Integer)+ m = solarMeanAnomaly u lw+ lambda = eclipticLongitude u lw++toJD :: RealFrac a => UTCTime -> a+toJD = (+2400000.5) . toMJD+ where+ toMJD (UTCTime (fromIntegral . toModifiedJulianDay -> d) (toRational -> dt)) =+ fromRational (d + dt / 86401)++jdToSeconds :: (RealFrac a, Integral b) => a -> b+jdToSeconds jd = floor (dayFrac * 86401)+ where+ dayFrac = mjd - fromIntegral (floor mjd :: Integer)+ mjd = jd - 2400000.5++julianCycle :: Integral a => UTCTime -> LongitudeWest -> a+julianCycle u lw = n+ where+ n = floor (nstar + 0.5)+ nstar = jdate - 2451545.0009 - (lw / 360)+ jdate = toJD u++approxSolarNoon :: UTCTime -> LongitudeWest -> Double+approxSolarNoon u lw = jstar+ where+ jstar = 2451545.0009 + lw / 360 + fromIntegral (julianCycle u lw :: Int)++solarMeanAnomaly :: UTCTime -> LongitudeWest -> Degrees Double+solarMeanAnomaly u lw = Degrees m+ where+ m = (357.5291 + 0.98560028 * (approxSolarNoon u lw - 2451545)) `mod'` 360++equationOfCenter :: UTCTime -> LongitudeWest -> Double+equationOfCenter u lw = c+ where+ c = 1.9148 * sine m + 0.0200 * sine (2 * m) + 0.0003 * sine (3 * m)+ m = solarMeanAnomaly u lw++eclipticLongitude :: UTCTime -> LongitudeWest -> Degrees Double+eclipticLongitude u lw = Degrees lambda+ where+ lambda = (m + 102.9372 + c + 180) `mod'` 360+ Degrees m = solarMeanAnomaly u lw+ c = equationOfCenter u lw++solarTransit :: UTCTime -> LongitudeWest -> Double+solarTransit u lw = jtransit+ where+ jtransit = jstar + 0.0053 * sine m - 0.0069 * sine (2 * lambda)+ jstar = approxSolarNoon u lw+ m = solarMeanAnomaly u lw+ lambda = eclipticLongitude u lw++declination :: UTCTime -> LongitudeWest -> Degrees Double+declination u lw = arcsine (sine lambda * sine (Degrees 23.45))+ where+ lambda = eclipticLongitude u lw++omega0 :: UTCTime -> LongitudeWest -> LatitudeNorth -> Degrees Double+omega0 u lw ln = arccosine (num / denom)+ where+ num = sine (Degrees (-0.83)) - sine phi * sine gamma'+ denom = cosine phi * cosine gamma'+ phi = Degrees ln+ gamma' = declination u lw++mkUTC :: Day -> Integer -> UTCTime+mkUTC d = UTCTime d . secondsToDiffTime