# Astro

![Build Status](

Astro is a library to provide basic astromonomical functions with a focus on functions that support solar, lunar and lunisolar calendars such as the Chinese, Hebrew and Persian calendars.

## Usage

**NOTE: It's important to install and configure `Astro` correctly before use. See the [installation](#installation) notes below.**

The primary functions are:

* `Astro.sunrise/3`
* `Astro.sunset/3`
* `Astro.solstice/2`
* `Astro.equinox/2`
* `Astro.hours_of_daylight/2`

### Examples
  # Sunrise in Sydney on December 4th
  iex> Astro.sunrise({151.20666584, -33.8559799094}, ~D[2019-12-04])
  {:ok, #DateTime<2019-12-04 05:37:00.000000+11:00 AEDT Australia/Sydney>}

  # Sunset in Sydney on December 4th
  iex> Astro.sunset({151.20666584, -33.8559799094}, ~D[2019-12-04])
  {:ok, #DateTime<2019-12-04 19:53:00.000000+11:00 AEDT Australia/Sydney>}

  # Sunset in the town of Alert in Nunavut, Canada
  # ...doesn't exist since there is no sunset in summer
  iex> Astro.sunset({-62.3481, 82.5018}, ~D[2019-07-01])
  {:error, :no_time}

  # ...or sunrise in winter
  iex> Astro.sunrise({-62.3481, 82.5018}, ~D[2019-12-04])
  {:error, :no_time}

  # Hours of daylight on December 7th in Sydney
  iex> Astro.hours_of_daylight {151.20666584, -33.8559799094}, ~D[2019-12-07]
  {:ok, ~T[14:18:45]}

  # No sunset in summer at high latitudes
  iex> Astro.hours_of_daylight {-62.3481, 82.5018}, ~D[2019-06-07]
  {:ok, ~T[23:59:59]}

  # No sunrise in winter at high latitudes
  iex> Astro.hours_of_daylight {-62.3481, 82.5018}, ~D[2019-12-07]
  {:ok, ~T[00:00:00]}

  # Calculate solstices for 2019
  iex> Astro.solstice 2019, :december
  {:ok, ~U[2019-12-22 04:18:57Z]}

  iex> Astro.solstice 2019, :june
  {:ok, ~U[2019-06-21 15:53:45Z]}

  # Calculate equinoxes for 2019
  iex> Astro.equinox 2019, :march
  {:ok, ~U[2019-03-20 21:58:06Z]}

  iex> Astro.equinox 2019, :september
  {:ok, ~U[2019-09-23 07:49:30Z]}

### Specifying a location

The desired location of sunrise or sunset can be specified as either:

* a tuple of longitude and latitude (note the order) such as `{-62.3481, 82.5018}`
* a tuple of longitude, latitude and elevation (note the order) such as `{-62.3481, 82.5018, 0}`.
* a `Geo.Point.t` struct
* a `Geo.PointZ.t` struct

### Location units and direction

For this implementation, the latitude and longitude of the functions in `Astro` are specified as follows:

* Longitude is `+` for eastern longitudes and `-` for western longitudes and specified in degrees
* Latitude is `+` for northern latitudes and `-` for southern latitudes and specified in degrees
* Elevation is specified in meters

## References

* Thanks to @pinnymz for the [ruby-zmanim]( gem which has a well structured ruby implementation of sunrise / sunset and some core astronomical algorithms.

* Eventually all roads lead to the canonical book on the subject by Jean Meeus: [Astronomical Algorithms](

* For the intersection of calendars and astronomy, [Calendrical Calculations]( by Nachum Dershowitz and Edward M. Reingold remains the standard reference.

* On the web, []( is a great reference. The sunrise/sunset calculations in this library are tested to return times within 1 minute of results.

* [Wikipedia]( for content to help describe the understanding behind some of the functions

## Installation

### Configure Astro
Astro can be installed by adding `astro` to your list of dependencies in `mix.exs`:

def deps do
    {:astro, "~> 0.7.0"}

### Install TzWorld Data
Then get dependencies and install the data required to determine a time zone from a location which is used by the dependency `tz_world`.

mix deps.get
mix tz_world.update

### Add TzWorld to supervision tree

It is also required that `tz_world` be added to your applications supervision tree by adding the relevant `tz_world` backend to it in your `MyApp.Application` module:
defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      # See the documentation for tz_world for the
      # various available backends. This is the recommended
      # backend.

    opts = [strategy: :one_for_one, name: Astro.Supervisor]
    Supervisor.start_link(children, opts)

### Configure your application module

Make sure that you have configured your application in `mix.exs`:
  def application do
      mod: {MyApp.Application, [strategy: :one_for_one]},

Documentation can be found at [](