in reply to Re^5: Moon phase on historical events
in thread Moon phase on historical events

Thanks for this. It works for trump's (real) tower but scylla is shown to be somewhere near Hades (for a country with planetal ambitions, their map services are curiously modest to confine within the national boundaries and that "feet" default indicates possible time-warp to past eras):

Trump has been relegated to a third-world nation (Florida), and with the guvmint, it seems to depend on who and how you ask:

fritz@hogan-Lenovo-IdeaPad-S145-15IWL:~/Documents$ ./7.mp.pl Subroutine get_logger redefined at ./7.mp.pl line 41. INFO: ./7.mp.pl in new scylla on 2022-02-18T03:22:31 (1645150951 seconds unix-epoch) t +imezone: Europe/Rome (lat: 38.1737884469946, lon: 15.8364278983988) Moon age: 16.1131124830837 days Moon phase: 54.6 % of cycle (birth-to-death) Moon's illuminated fraction: 98.0 % of full disc important moon phases around the event: New Moon = Mon Jan 31 22:49:10 2022 First quarter = Tue Feb 8 06:51:53 2022 Full moon = Wed Feb 16 09:59:41 2022 Last quarter = Wed Feb 23 15:34:32 2022 New Moon = Wed Mar 2 10:38:16 2022 end event. INFO: return from the google is 1291 meters INFO: in new scylla on 2022-02-18T03:22:31 (1645150951 seconds unix-ep +och) timezone: Europe/Rome (lat: 38.1737884469946, lon: 15.8364278983 +988) at height 1293 meters INFO: Object Azimuth Elevation INFO: Venus 103.996877720637 -9.60439269992599 INFO: Jupiter 57.162019344654 -45.6099678242824 INFO: Moon 232.083188637894 50.0250955497636 INFO: Saturn 84.3881395776426 -34.0613320748201 fritz@hogan-Lenovo-IdeaPad-S145-15IWL:~/Documents$ cat 7.mp.pl #!/usr/bin/perl use v5.030; # strictness implied use warnings; use feature qw[ signatures ]; no warnings qw[ experimental::signatures ]; use Astro::Coord::ECI::Utils 'deg2rad'; use Astro::Coords; use Astro::MoonPhase; use Astro::Telescope; use Data::Dumper; use DateTime; use DateTime::Format::ISO8601; use DateTime::TimeZone; use Log::Log4perl; use Try::Tiny; our $debug = 0; my $time_str = "03:22:31"; my $alt = 0; my $date_str = "2022-02-18"; my @events = ( { "name" => "in new scylla", "date" => $date_str, "time" => $time_str, "location" => { lon => 15.83642789839883, lat => 38.17378844699463 + }, }, ); # Not wanting to divine the configuration file for Log::Log4perl, modu +le used in # the query. Better for SSCCE considerations. thx parv { package Log::Log4perl; sub get_logger ($pkg) { return bless [], $pkg; } sub show (@arg) { warn @arg, "\n"; } sub debug ( $ignore, @rest ) { show( 'DEBUG: ', @rest ); } sub info ( $ignore, @rest ) { show( 'INFO: ', @rest ); } sub warn ( $ignore, @rest ) { show( 'WARNING: ', @rest ); } sub error ( $ignore, @rest ) { die 'ERROR: ', @rest, "\n"; } } my $logger = Log::Log4perl->get_logger(); $logger->info("$0"); ## event loop for my $event (@events) { my $epoch = parse_event($event); print event2str($event) . "\n"; my ( $MoonPhase, $MoonIllum, $MoonAge, $MoonDist, $MoonAng, $SunDist, $SunAng ) = phase($epoch); print "Moon age: $MoonAge days\n"; print "Moon phase: ".sprintf("%.1f", 100.0*$MoonPhase)." % of cycl +e (birth-to-death)\n"; print "Moon's illuminated fraction: ",sprintf("%.1f", 100.0*$MoonI +llum)." % of full disc\n"; print "important moon phases around the event:\n"; my @phases = phasehunt($epoch); print " New Moon = ", scalar(localtime($phases[0])), "\n"; print " First quarter = ", scalar(localtime($phases[1])), "\n"; print " Full moon = ", scalar(localtime($phases[2])), "\n"; print " Last quarter = ", scalar(localtime($phases[3])), "\n"; print " New Moon = ", scalar(localtime($phases[4])), "\n"; print "end event.\n\n"; ## determine altitude # usage: die unless exists $event->{location}; # restriction my $return = get_elevation_from_coordinates( $event->{location}->{la +t}, $event->{location}->{lon}, $debug ); $logger->info("return from the google is $return meters"); my $observer = $return + 2; #(most people stand) $logger->info( event2str($event) . " at height $observer meters" ); $logger->info("Object\tAzimuth\t\tElevation"); for my $name (qw/Venus Jupiter Moon Saturn/) { my $planet = Astro::Coords->new( planet => $name ); # use DateTime my $date = DateTime->from_epoch( epoch => $epoch, time_zone => 'UT +C' ); $planet->datetime($date); $planet->telescope( Astro::Telescope->new( Name => $event->{name}, Long => deg2rad( $event->{location}->{lon} ), Lat => deg2rad( $event->{location}->{lat} ), Alt => $observer, #meters above +sea level ) ); my $az = $planet->az( format => 'deg' ); my $el = $planet->el( format => 'deg' ); $logger->info("$name\t$az\t\t$el"); } ## end planets loop } ## end event loop sub event2str { my $event = shift; if ( !exists $event->{_is_parsed} ) { warn "event has not been parsed, just dumping it..."; print Dump($event); } my $str = $event->{name} . " on " . $event->{datetime} . " (" . $event->{datetime}->epoch . " seconds unix-epoch)" . " timezone: " . $event->{datetime}->time_zone->name; if ( exists $event->{location} ) { if ( ref( $event->{location} ) eq 'HASH' ) { $str .= " (lat: " . $event->{location}->{lat} . ", lon: " . $event->{location}->{lon} . ")"; } else { $str .= "(" . $event->{location} . ")" } } return $str; } sub parse_event { my $event = shift; $debug //= 0; if ( !exists $event->{date} ) { die "date field is missing from even +t." } my $datestr = $event->{date}; die "event does not have a 'name' field, please specify one, anythin +g really." unless exists $event->{name}; my $timestr = "00:00:01"; if ( exists $event->{time} ) { $timestr = $event->{time}; print "event2epoch(): setting time to '$timestr' ...\n" if $debug > 0; die "time '$timestr' is not valid, it must be in the form 'hh:mm:s +s'." unless $timestr =~ /^\d{2}:\d{2}:\d{2}$/; } else { $event->{time} = $timestr } my $isostr = $datestr . 'T' . $timestr; my $dt = DateTime::Format::ISO8601->parse_datetime($isostr); die "failed to parse date '$isostr', check date and time fields." unless defined $dt; $event->{datetime} = $dt; my $tzstr = 'UTC'; if ( exists $event->{timezone} ) { $tzstr = $event->{timezone}; print "event2epoch(): found a timezone via 'timezone' field as '$tzstr' (tha +t does not mean it is valid) ...\n" if $debug > 0; } elsif ( exists $event->{location} ) { my $loc = $event->{location}; if ( ( ref($loc) eq '' ) && ( $loc =~ /^[a-zA-Z]$/ ) ) { # we have a location string my @alltzs = DateTime::TimeZone->all_names; my $tzstr; for (@alltzs) { if ( $_ =~ /$loc/i ) { $tzstr = $_; last } } die "event's location can not be converted to a timezone, consider specify +ing the 'timezone' directly or setting 'location' coordinates with: \ +[lat,lon\]." unless $tzstr; print "event2epoch(): setting timezone via 'location' name to '$timestr' ... +\n" if $debug > 0; } elsif ( ( ref($loc) eq 'HASH' ) && ( exists $loc->{lat} ) && ( exists $loc->{lon} ) ) { # we have a [lat,lon] array for location require Geo::Location::TimeZone; my $gltzobj = Geo::Location::TimeZone->new(); $tzstr = $gltzobj->lookup( lat => $loc->{lat}, lon => $loc->{lon +} ); if ( !$tzstr ) { die "timezone lookup from location coordinates lat:" . $loc->{lat} . ", lon:" . $loc->{lon} . " has failed."; } print "event2epoch(): setting timezone via 'location' coordinate +s lat:" . $loc->{lat} . ", lon:" . $loc->{lon} . " ...\n" if $debug > 0; } } if ($tzstr) { print "event2epoch(): deduced timezone to '$tzstr' and setting it +...\n" if $debug > 0; try { $dt->set_time_zone($tzstr) } catch { die "$_\n failed to set the timezone '$tzstr', is it valid?" } } $event->{_is_parsed} = 1; $event->{epoch} = $dt->epoch; return $event->{epoch}; } sub get_elevation_from_coordinates { my ( $lat, $lon, $debug ) = @_; use LWP::UserAgent; use HTTP::Request; use Data::Roundtrip; $debug //= 0; my $ua = LWP::UserAgent->new( agent => 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox +/78.0', ); my $response; my $payload = 'latitude=' . $lat . '&longitude=' . $lon . '&application_max_assets_mtime=1559625591'; my $payloadlen = length($payload); # this request was translated from Curl command-line # by [Corion]'s https://corion.net/curl2lwp.psgi my $req = HTTP::Request->new( 'POST' => 'https://www.mapcoordinates.net/admin/component/edit/Vpc_MapCoordinate +s_Advanced_GoogleMapCoords_Component/Component/json-get-elevation', [ 'Connection' => 'keep-alive', 'Accept' => '*/*', 'Accept-Encoding' => 'gzip, x-gzip, deflate, x-bzip2, bzip2', 'Accept-Language' => 'en-US,en;q=0.5', # 'Host' => 'www.mapcoordinates.net:443', 'Referer' => 'https://www.mapcoordinates.net/en', 'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firef +ox/78.0', 'Content-Length' => $payloadlen, 'Content-Type' => 'application/x-www-form-urlencoded; charse +t=UTF-8', 'DNT' => '1', 'Origin' => 'https://www.mapcoordinates.net', 'X-Requested-With' => 'XMLHttpRequest' ], $payload ); die "call to HTTP::Request has failed" unless $req; if ( $debug > 0 ) { $logger->debug( "$0 : $payload\n$0 : sending above payload, of $payloadlen bytes +..."); } $response = $ua->request($req); die "Error fetching: " . $response->status_line unless $response->is_success; my $content = $response->decoded_content; my $data = Data::Roundtrip::json2perl($content); die "failed to parse received data:\n$content\n" unless exists $data->{'elevation'}; return $data->{'elevation'}; } __END__ fritz@hogan-Lenovo-IdeaPad-S145-15IWL:~/Documents$

My units are meters here from what we did before, but Americans won't understand what doesn't comport with their religion: football.