Is there a simple open-source, command-line program that can show the sunrise and sunset times at a given date and location, and perhaps moon and planet data as well?

Browsing the Debian package database and Google searches, I can't find anything relevant. This surprises me — considering the number of people who are both astronomy geeks and unix geeks, I'd have expected a de-facto-standard sunrise(1) (or perhaps sunrise(6)).

I am not interested in more complex programs that incidentally perform the calculations, such as sky maps (celestia, kstars, starplot, stellarium), earth maps (sunclock, xplanet), calendars/agendas (emacs, remind), clocks (glunarclock, wmsun), tide almanachs (xtide). There is perhaps aa (astronomical-almanac), but I don't see a simple way of asking it what time the sun will rise on this date at these longitude and latitude.

What did I miss?

8 Answers 8


Did you try sunwait?

Sunwait is a small C program for calculating sunrise and sunset, as well as civil, nautical, and astronomical twilights. [..]

The project is available on GitHub and can be cloned as follows:

$ git clone https://github.com/risacher/sunwait
Cloning into 'sunwait'...
remote: Enumerating objects: 107, done.
remote: Counting objects: 100% (62/62), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 107 (delta 45), reused 37 (delta 36), pack-reused 45
Receiving objects: 100% (107/107), 121.93 KiB | 2.65 MiB/s, done.
Resolving deltas: 100% (55/55), done.
$ cd sunwait/

After fixing issues with parentheses, the program can be built

$ make
gcc -c -Wall  sunwait.cpp -o sunwait.o
gcc -c -Wall  sunriset.cpp -o sunriset.o
sunriset.cpp: In function ‘void sun_RA_dec(double, double*, double*, double*)’:
sunriset.cpp:151:18: warning: variable ‘zs’ set but not used [-Wunused-but-set-variable]
  151 |   double xs, ys, zs;
      |                  ^~
gcc -c -Wall  print.cpp -o print.o
gcc sunwait.o sunriset.o print.o -o sunwait -lm -lstdc++
$ ./sunwait help
Calculate sunrise and sunset times for the current or targetted day.
The times can be adjusted either for twilight or fixed durations.

The program can either: wait for sunrise or sunset   (function: wait),
  or return the time (GMT or local) the event occurs (function: list),
  or report the day length and twilight timings      (function: report),
  or simply report if it is DAY or NIGHT             (function: poll).

You should specify the latitude and longitude of your target location.

Usage: sunwait [major options] [minor options] [twilight type] [rise|set] [offset] [latitude] [longitude]

Major options, either:
    poll          Returns immediately indicating DAY or NIGHT. See 'program exit codes'. Default.
    wait          Sleep until specified event occurs. Else exit immediate.
    list [X]      Report twilight times for next 'X' days (inclusive). Default: 1.
    report        Generate a report about the days sunrise and sunset timings.

Minor options, any of:
    [no]debug     Print extra info and returns in one minute. Default: nodebug.
    [no]version   Print the version number. Default: noversion.
    [no]help      Print this help. Default: nohelp.
    [no]gmt       Print times in GMT or local-time.  Default: nogmt.

Twilight types, either:
    daylight      Top of sun just below the horizon. Default.
    civil         Civil Twilight.         -6 degrees below horizon.
    nautical      Nautical twilight.     -12 degrees below horizon.
    astronomical  Astronomical twilight. -18 degrees below horizon.
    angle [X.XX]  User-specified twilight-angle (degrees). Default: 0.

Sunrise/sunset. Only useful with major-options: 'wait' and 'list'. Any of: (default: both)
    rise          Wait for the sun to rise past specified twilight & offset.
    set           Wait for the sun to  set past specified twilight & offset.

    offset [MM|HH:MM] Time interval (+ve towards noon) to adjust twilight calculation.

Target date. Only useful with major-options: 'report' or 'list'. Default: today
    d [DD]        Set the target Day-of-Month to calculate for. 1 to 31.
    m [MM]        Set the target Month to calculate for. 1 to 12.
    y [YYYY]      Set the target Year to calculate for. 2000 to 2099.

latitude/longitude coordinates: floating-point degrees, with [NESW] appended. Default: Bingham, England.

Exit (return) codes:
    0           OK: exit from 'wait' or 'list' only.
    1           Error.
    2           Exit from 'poll': it is DAY or twilight.
    3           Exit from 'poll': it is NIGHT (after twilight).

Example 1: sunwait wait rise offset -1:15:10 51.477932N 0.000000E
Wait until 1 hour 15 minutes 10 secs before the sun rises in Greenwich, London.

Example 2: sunwait list 7 civil 55.752163N 37.617524E
List civil sunrise and sunset times for today and next 6 days. Moscow.

Example 3: sunwait poll exit angle 10 54.897786N -1.517536E
Indicate by program exit-code if is Day or Night using a custom twilight angle of 10 degrees above horizon. Washington, UK.

Example 4: sunwait list 7 gmt sunrise angle 3
List next 7 days sunrise times, custom +3 degree twilight angle, default location.
Uses GMT; as any change in daylight saving over the specified period is not considered.

Note that program uses C library functions to determine time and localtime.
Error for timings are estimated at: +/- 4 minutes.

To install it globally, type:

$ sudo install -vpm 755 sunwait /usr/local/bin/
'sunwait' -> '/usr/local/bin/sunwait'

I ended up using Perl's DateTime::Event::Sunrise, because it tends to be easier for me to deploy a module from CPAN than to compile C programs.

Sample usage:

use DateTime;
use DateTime::Astro::Sunrise;
$latitude = "+48.857"; $longitude = "+2.351"; 
$sr = DateTime::Astro::Sunrise->new($longitude, $latitude, 0, 3);
$date = DateTime->now; $date->set_time_zone("local");
($rise, $set) = $sr->sunrise($date);
$rise->set_time_zone("local"); $set->set_time_zone("local");
print $rise, " to ", $set, "\n";

My sunrise script.


For lazy bones as I am there is a very simple program called hdate, available in many distributions (apt-get install hdate on Debian/Ubuntu/…):

hdate -s -l N50 -L E14 -z2


Wednesday, 26 June 2019, 23 Sivan 5779
sunrise: 04:55
sunset: 21:17


  • -s sunset sunrise
  • -l, -L: Altitude and Latitude of Prague (50°05′N 14°25′E)
  • -z zone: SELC=+2

תודה רבה יהודים חכמים. :-)


For Python there's the astral module. It's not command line, but implementing a command line program using it should be trivial (like your Perl example). Documentation and examples are at http://astral.readthedocs.io/en/latest/index.html.


Check out this Linux Home Automation Linux Home Automation site and search the page for "sunrise". There are some command line programs there from c. 1985 that are pretty minimalist. I have the source code for a number of related programs from that era, but I can't find them on the web.

Update: I just found the source for a few others, including sdate, on this Event Logger page. Search the page for "rise_set".

Update 2017-12-23: The Linux Home Automation project has moved, but it looks like the command-line programs for sunrise, sunset, etc., are still available here and here. I crossed out the link to the original page but kept it for reference and added a link to the new page.


This https://github.com/Aygath/zon program prints what you want, for sun rise/set/azimuth-altitude.

In the "releases" of my github you will find a .deb installation file for amd64 Debian and Ubuntu. It will build on ARM (raspberry pi) as well.

Moon data is in my plans, but not implemented yet.

It is suitable for your personal scheduling needs. It is targeted at scheduling with "systemd-run --calendar" or "at" command.


If you already have Dianne Skoll's remind installed―and you should, if you want an excellent command-line reminders program―it will do this. Create a "reminders" file, e.g., sun.rem, containing these two lines:

REM Sunrise: [sunrise()] Sunset: [sunset()]

and run it thus:

remind sun.rem

It also offers dates around moon phases. I haven't figured out the fine points of those yet.

Another possibility, suggested by Ms. Skoll in the mailing list:

# File day-or-night.rem
IF now() < sunrise() || now() > sunset()
    MSG night%
    MSG day%

I switched to that because it saves me a call to awk.

Here's a shell script that supports custom dates and locations.


set -eu

date= # today
longitude=2.352 latitude=48.857 # Paris
NAME='Sunrise/sunset' FUNCTION1='sunrise' FUNCTION2='sunset'

usage () {
  cat <<EOF
Usage: $0 [-d DATE]
Show the sunrise and sunset times.
This program requires remind (https://dianne.skoll.ca/projects/remind/).

  -a ALT    Sun altitude (ALT=(civil|nautical|sun))
  -d DATE   Date (default: today).
  -x NUM    longitude (degrees, >0 for east or xxxE or xxxW)
  -y NUM    latitude (degrees, >0 for north or xxxN or xxxS)

while getopts a:d:x:y: OPTLET; do
  case $OPTLET in
      case $OPTARG in
        # Sloppy validation to keep things simple
        [Aa]*) NAME='Astronomical' FUNCTION1='adawn' FUNCTION2='adusk';;
        [Cc]*) NAME='Civil' FUNCTION1='dawn' FUNCTION2='dusk';;
        [Nn]*) NAME='Nautical' FUNCTION1='ndawn' FUNCTION2='ndusk';;
        [Ss]*) NAME='Sunrise/sunset' FUNCTION1='sunrise' FUNCTION2='sunset';;
        *) echo 1>&2 "Invalid altitude specification: $OPTARG"; exit 120;;
      date="'$(date -d "$OPTARG" +%Y-%m-%d)'";;
      case $OPTARG in
        *[Ee]) longitude=${OPTARG%?};;
        -*[Ww]) longitude=${OPTARG%?}; longitude=${longitude#-};;
        *[Ww]) longitude=-${OPTARG%?};;
        *) longitude=$OPTARG;;
      case $OPTARG in
        *[Nn]) latitude=${OPTARG%?};;
        -*[Ss]) latitude=${OPTARG%?}; latitude=${latitude#-};;
        *[Ss]) latitude=-${OPTARG%?};;
        *) latitude=$OPTARG;;
    ?) usage >&2; exit 120;;

remind - <<EOF
SET \$Longitude "$longitude"
SET \$Latitude "$latitude"
REM $date $NAME: [$FUNCTION1($date)] [$FUNCTION2($date)]%
  • @Gilles 'SO- stop being evil' You really should put the script you wrote in its own answer rather than letting me get credit for it.
    – MDeBusk
    Feb 22 at 23:23

Btw, in Plan 9 from outer sp... er, Bell Labs, it's astro.

enter image description here


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .