Astro-Montenbruck
    
    
  
  
  
view release on metacpan or search on metacpan
and the planets with precision that is approximately the same as that found in
astronomical yearbooks. Other modules contain time-related routines, coordinates
conversions, calculation of the ecliptic obliquity and nutation, etc. Over time,
the range of utility functions will grow.
Partially it overlaps some code which already exists in CPAN and elsewhere.
For instance, there is a Perl wrapper for Swiss Ephemeris,
http://www.astrotexte.ch/sources/SwissEph.html. Swiss Ephemeris is fast and
precise C library. Unfortunately, it lacks portability and convenient license.
So, it is not easy for a layman to customize it for her custom application, be
it an online lunar calendar, or tool for amateur sky observations.
The present library is an attempt to find a middle-ground between precision on
the one hand and compact, well organized code on the other. I tried to follow the
best practices of modern Perl programming.
PRECISION
As the book authors state in Introduction to the 4-th edition,
"The errors in the fundamental routines for determining the coordinates of the
Sun, the Moon, and the planets amount to about 1â³-3â³.
  - [Scripts](#scripts)
    - [Example](#example)
  - [How to contribute](#how-to-contribute)
  - [License And Copyright](#license-and-copyright)
## Overview
Library of astronomical calculations, based on _"Astronomy On The Personal Computer"_ by _O.Montenbruck_ and _T.Phleger_, _Fourth Edition, Springer-Verlag, 2000_.
The main purpose of the library is to calculate positions of the Sun, the Moon, and the planets with precision that is approximately the same as that found in astronomical yearbooks. Other modules contain time-related routines, coordinates conversion...
Partially it overlaps some code which already exists in CPAN and elsewhere. For instance, there is a [Perl wrapper for Swiss Ephemeris](http://www.astrotexte.ch/sources/SwissEph.html). Swiss Ephemeris is fast and precise C library. Unfortunately, it ...
The present library is an attempt to find a middle-ground between precision on the one hand and compact, well organized code on the other. I tried to follow the best practices of modern Perl programming.
## Precision
As the book authors state in Introduction to the 4-th edition, _"The errors in the fundamental routines for determining the coordinates of the Sun, the Moon, and the planets amount to about 1â³-3â³._
## Contents
- [Astro::Montenbruck::MathUtils](lib/Astro/Montenbruck/MathUtils.pm) â Core mathematical routines.
lib/Astro/Montenbruck.pm view on Meta::CPAN
=head1 DESCRIPTION
Library of astronomical calculations, based mainly on
I<"Astronomy On The Personal Computer"> by I<O.Montenbruck> and I<T.Phleger>,
I<Fourth Edition, Springer-Verlag, 2000>.
There are many astronomical libraries available in the public domain. While
giving accurate results, they often suffer from lack of convenient API,
documentation and maintainability. Most of the source code is written in C, C++
or Java, and not dynamic languages. So, it is not easy for a layman to customize
them for her custom application, be it an online lunar calendar, or tool for
amateur sky observations. This library is an attempt to find a middle-ground
between precision on the one hand and compact, well organized code on the other.
=head2 Accuracy
As authors of the book state, they have tried to obtain an accuracy that is
approximately the same as that found in astronomical yearbooks.
"The errors in the fundamental routines for determining the coordinates
of the Sun, the Moon, and the planets amount to about 1â³-3â³."
lib/Astro/Montenbruck/RiseSet.pm view on Meta::CPAN
Sun altitude is B<-6 deg>. Civil twilight is the brightest form of twilight.
There is enough natural sunlight during this period that artificial light may
not be required to carry out outdoor activities. Only the brightest celestial
objects can be observed by the naked eye during this time.
=back
=head1 CAVEATS
Sometimes rise and set happen on different calendar dates. For example, here is the output of C<riseset.pl>
script:
  $ perl .\script\riseset.pl --date=1989-03-28 --place=48.1 -11.6 --timezone=UTC
  Date      :  1989-03-28 UTC
  Place     :  48N06, 011E35
  Time Zone :  UTC
          rise       transit    set     
  Moon    23:34:17   03:23:59   07:10:54
lib/Astro/Montenbruck/Time.pm view on Meta::CPAN
use Exporter qw/import/;
our $SEC_PER_DAY = 86400;        # Seconds per day
our $SEC_PER_CEN = 3155760000;
our $J2000       = 2451545;      # Standard Julian Date for 1.1.2000 12:00
our $J1900       = 2415020
  ;    # Standard Julian Date for  31.12.1899 12:00 (astronomical epoch 1900.0)
our $SOLAR_TO_SIDEREAL = 1.002737909350795
  ;    # Difference in between Sidereal and Solar hour (the former is shorter)
our $GREGORIAN_START = 15821004;    # Start of Gregorian calendar (YYYYMMDD)
our $JD_UNIX_EPOCH = _gmtime2jd( gmtime(0) )
  ; # Standard Julian date for the beginning of Unix epoch, Jan 1 1970 on most Unix systems
our %EXPORT_TAGS = (
    all => [
        qw/jd_cent after_gregorian cal2jd jd2cal jd0 unix2jd jd2mjd mjd2jd
          jd2unix jdnow t1900 jd2gst jd2lst
          is_leapyear day_of_year
          $SEC_PER_DAY $SEC_PER_CEN $J2000 $J1900 $GREGORIAN_START $JD_UNIX_EPOCH/
    ],
lib/Astro/Montenbruck/Time.pm view on Meta::CPAN
-584.
In this module all subroutines accepting year assume that B<there is year zero>.
Thus, the sequence of years is: C<BC -3, -2, -1, 0, 1, 2, 3, AD>.
=head2 Date and Time
Time is represented by fractional part of a day. For example, 7h30m UT
is C<(7 + 30 / 60) / 24 = 0.3125>.
=head3 Gregorian calendar
I<Civil calendar> in most cases means I<proleptic Gregorian calendar>. it is
assumed that Gregorian calendar started at Oct. 4, 1582, when it was first
adopted in several European countries. Many other countries still used the older
Julian calendar. In Soviet Russia, for instance, Gregorian system was accepted
on Jan 26, 1918. See:
L<https://en.wikipedia.org/wiki/Gregorian_calendar#Adoption_of_the_Gregorian_Calendar>
=head1 EXPORTED CONSTANTS
=over
=item * C<$SEC_PER_DAY> seconds per day (86400)
=item * C<$SEC_PER_CEN> seconds per century (3155760000)
=item * C<$J2000> Standard Julian date for start of epoch 2000,0 (2451545)
=item * C<$J1900> Standard Julian date for start of epoch 1900,0 (2415020)
=item * C<$GREGORIAN_START> Start of Gregorian calendar, YYYYMMDD (15821004)
=item * C<$JD_UNIX_EPOCH> Standard Julian date for start of the Unix epoch
=back
=head1 EXPORTED FUNCTIONS
=over
=item * L</jd_cent($jd)>
lib/Astro/Montenbruck/Time.pm view on Meta::CPAN
=back
=head1 FUNCTIONS
=head2 jd_cent($jd)
Convert Standard Julian Date to centuries passed since epoch 2000.0
=head2 after_gregorian($year, $month, $date, gregorian_start => $YYYYMMDD )
Does the given date fall to period after Gregorian calendar?
=head3 Positional Arguments
=over
=item * B<year> (astronomic, zero-based)
=item * B<month> (1-12)
=item * B<date> UTC date (1-31) with hours and minutes as decimal part
=back
=head3 Optional Named Arguments
=over
=item *
B<gregorian_start> â start of Gregorian calendar. Default value is
B<15821004> If the date is Julian ("old style"), use C<undef> value.
To provide non-standard start of Gregorian calendar, provide a number
in format YYYYMMDDD, e.g. C<19180126> for Jan 26, 1918.
=back
=head3 Returns
I<true> or I<false>=.
=head2 cal2jd($year, $month, $date)
Convert civil date/time to Standard Julian date.
If C<gregorian_start> argument is not provided, it is assumed that this is a date
of I<Proleptic Gregorian calendar>, which started at Oct. 4, 1582.
=head3 Positional Arguments:
=over
=item * B<year> (astronomic, zero-based)
=item * B<month> (1-12)
=item * B<date> UTC date (1-31) with hours and minutes as decimal part
=back
=head3 Optional Named Arguments
=over
=item *
gregorian_start â start of Gregorian calendar. Default value is
B<15821004> If the date is Julian ("old style"), use C<undef> value.
To provide non-standard start of Gregorian calendar, provide a number
in format YYYYMMDDD, e.g. C<19180126> for Jan 26, 1918.
=back
=head3 Returns
Standard Julian date
=head2 jd2cal($jd)
lib/Astro/Montenbruck/Time.pm view on Meta::CPAN
=over
=item * gregorian â if i<true>, the result will be old-style (Julian) date
=back
=head3 Returns
A list corresponding to the input values of L</cal2jd($year, $month, $date)> function.
The date is given in the proleptic Gregorian calendar system unless B<gregorian>
flag is set to I<true>.
=head2 jd0($jd)
Given Standard Julian Date, calculate Standard Julian date for midnight of the same date.
=head2 unix2jd($seconds)
Given Unix (POSIX) time, in seconds, convert it to Standard Julian date.
script/moon_almanac.pl view on Meta::CPAN
=over 4
=item B<--help>
Prints a brief help message and exits.
=item B<--start>
Start date, in B<YYYY-DD-MM> format, current date by default.
  --start=2019-06-08 # calendar date
=item B<--days>
Number of days to process, B<1> by default  
=item B<--step>
Step between successive cevents, in days, B<7> by default  
=item B<--timezone>
script/phases.pl view on Meta::CPAN
=head1 OPTIONS
=over 4
=item B<--help>
Prints a brief help message and exits.
=item B<--date>
Date, either a I<calendar entry> in format C<YYYY-MM-DD>, or a floating-point I<Julian Day>:
  --date=2019-06-08 # calendar date
  --date=2438792.99 # Julian date
=item B<--timezone>
Time zone name, e.g.: C<EST>, C<UTC>, C<Europe/Berlin> etc. 
or I<offset from Greenwich> in format B<+HHMM> / B<-HHMM>, like C<+0300>.
    --timezone=CET # Central European Time
    --timezone=EST # Eastern Standard Time
    --timezone=UTC # Universal Coordinated Time
script/planpos.pl view on Meta::CPAN
=item B<--help>
Prints a brief help message and exits.
=item B<--man>
Prints the manual page and exits.
=item B<--time>
Date and time, either a I<calendar entry> in format C<YYYY-MM-DD HH:MM Z>, or
C<YYYY-MM-DD HH:MM Z>, or a floating-point I<Julian Day>:
  --time="2019-06-08 12:00 +0300"
  --time="2019-06-08 09:00 UTC"
  --time=2458642.875
Calendar entries should be enclosed in quotation marks. Optional B<"Z"> stands for
time zone, short name or offset from UTC. C<"+00300"> in the example above means
I<"3 hours east of Greenwich">.
t/11-time.t view on Meta::CPAN
BEGIN {
	use_ok( 'Astro::Montenbruck::Time', qw/:all/ );
}
our @MONTH_NAMES = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
sub format_date {
	sprintf('%04d-%02d-%05.2f', @_)
}
subtest "Start of Gregorian calendar" => sub {
    plan tests => 3;
    ok(
        after_gregorian(1965, 2, 1),
        'Afret Gregorian reform'
    ) or diag('1965-02-01 should be after Gregorian calendar reform');
    ok(
        !after_gregorian(1582, 10, 3),
        'Before Gregorian reform'
    ) or diag('1582-10-03 should be before Gregorian calendar reform');
    ok(
        # in Soviet Russia Gregorian calendar was accepted on Jan 26, 1918
        !after_gregorian(1917, 11, 7, gregorian_start => 19180126),
        'Custom Gregorian start'
    ) or diag('1917-11-07 should be before given Gregorian calendar reform');
};
subtest "Conversions" => sub {
	my @cases = (
        #{ date => [ 1900, 1, 0.5 ],   jd => 2415020 },
    	{ date => [ 1984, 8, 29 ],    jd => 2445941.5 },
    	{ date => [ 1899, 12, 31.5 ], jd => 2415020 },
    	{ date => [ 1938, 8, 17 ],    jd => 2429127.5 },
    	{ date => [ 1, 1, 1 ],        jd => 1721423.5 },
        { date => [-4712, 7, 12 ],    jd => 192.5 },
t/11-time.t view on Meta::CPAN
	subtest "Calendar -> JD" => sub {
		plan tests => scalar @cases;
		for ( @cases ) {
			my $got = cal2jd( @{$_->{date}} );
            delta_ok($_->{jd}, $_->{jd}, format_date( @{$_->{date}} ))
                or diag("Expected: $_->{jd}, got: $got");
		}
	};
	subtest "JD -> calendar" => sub {
		plan tests => scalar @cases;
		for (@cases) {
            my @cal = jd2cal( $_->{jd} );
            my $got = format_date(@cal);
            my $exp = format_date( @{ $_->{date} } );
            cmp_ok($got, 'eq', $exp, "JD $_->{jd}")
                or diag("Expected: $exp, got: $got");
		}
	}
};
( run in 0.536 second using v1.01-cache-2.11-cpan-5dc5da66d9d )