# https://api.weather.gov/points/{latitude},{longitude} # https://api.weather.gov/points/45.4836356,-122.4170501 #### #!/usr/bin/env perl use strict; use warnings; use DateTime::Format::Strptime; use REST::Client; use Data::Roundtrip qw/:all/; use 5.016; use Log::Log4perl; my $log_conf3 = "/home/hogan/Documents/hogan/logs/conf_files/3.conf"; my $log_conf4 = "/home/hogan/Documents/hogan/logs/conf_files/4.conf"; #Log::Log4perl::init($log_conf3); #debug Log::Log4perl::init($log_conf4); #info my $logger = Log::Log4perl->get_logger(); $logger->info($0); # this is our fetcher, similar to LWP::UserAgent # but better suited for this kind of web service: REST my $rest = REST::Client->new() or die "failed to construct client"; # see examples in # https://www.weather.gov/documentation/services-web-api # set the host $rest->setHost('https://api.weather.gov'); # https://api.weather.gov/points/{latitude},{longitude} # https://api.weather.gov/points/45.4836356,-122.4170501 # and this is our query with lat,long specified above #my $query = "gridpoints/TOP/$lat,$long/forecast"; my $query = "gridpoints/PQR/120,99/forecast"; # make the request and check the response code, 200 is good my $response = $rest->GET($query) or die "failed to GET($query)"; if ( $rest->responseCode() != 200 ) { die "failed to GET(" . $rest->getHost() . "/$query) with " . $rest->responseCode(); } # we get back JSON my $jsonstr = $response->responseContent(); # convert JSON string to a perl variable my $pv = json2perl($jsonstr); if ( !defined $pv ) { die "something wrong with this alleged json : '$jsonstr'"; } # go to the interesting part my $forecasts = $pv->{'properties'}->{'periods'}; # or print it all and examine it # print perl2dump($pv); # we have some dates in the data in ISO8601 format # this is a parser to convert that date to a DateTime # object which we can query about things (like seconds-unix-epoch) my $dateparser = DateTime::Format::Strptime->new( # parses 2020-04-26T06:00:00-05:00, # %F then literal T then %T then timezone offset pattern => '%FT%T%z' ) or die "failed to DateTime::Format::Strptime->new()"; # we store each prediction in this hash, keyed on start-end dates # see below $key ### hash no longer at this scope ### make an array container my @ordered; my $refordered = \@ordered; my $index = 0; for my $aforecast (@$forecasts) { print "go: " . $aforecast->{'name'} . "\n"; # extract various things from 1 prediction record # examine the record like : print perl2dump($aforecast); # like "This Afternoon" #print perl2dump($aforecast); my $period_str = $aforecast->{'name'}; # start and end times of the prediction, convert them to objects my $start_time_str = $aforecast->{'startTime'}; say "start is $start_time_str"; my $start_time_dateobj = $dateparser->parse_datetime($start_time_str) or die "parsing date '$start_time_str'."; $start_time_dateobj->set_time_zone('America/Los_Angeles'); my $st = $start_time_dateobj->strftime('%Y-%m-%d-%H:%M:%S %Z'); my $end_time_str = $aforecast->{'endTime'}; my $end_time_dateobj = $dateparser->parse_datetime($end_time_str) or die "parsing date '$start_time_str'."; $end_time_dateobj->set_time_zone('America/Los_Angeles'); my $et = $end_time_dateobj->strftime('%Y-%m-%d-%H:%M:%S %Z'); # sunny? my $forecast_str = $aforecast->{'shortForecast'}; # temperature as a number, see later for the units my $temp = $aforecast->{'temperature'}; # new scope for hash my %parsed; # store this record/prediction in our %parsed hash # keyed on this: my $key = $start_time_str . " to " . $end_time_str; $parsed{$key} = { 'date-human-str' => $period_str, # edit: added this 'date-from' => $start_time_str, 'date-from-local' => $st, 'date-to' => $end_time_str, 'date-to-local' => $et, 'date-span-hours' => ( $end_time_dateobj->epoch() - $start_time_dateobj->epoch() ) / 3600, 'date-from-epoch' => $start_time_dateobj->epoch(), 'date-to-epoch' => $end_time_dateobj->epoch(), 'forecast-string' => $forecast_str, # we append temp unit to the key, e.g. 'F' 'forecast-temp-' . $aforecast->{'temperatureUnit'} => $temp, }; my $refparsed = \%parsed; $ordered[$index] = $refparsed; $logger->info( perl2dump $refparsed); ++$index; } __END__ #### 2020/05/01 08:59:21 INFO ./1.6.weather.pl 2020/05/01 08:59:21 INFO $VAR1 = { '2020-05-01T08:00:00-07:00 to 2020-05-01T18:00:00-07:00' => { 'date-from-epoch' => 1588345200, 'date-span-hours' => '10', 'date-to-local' => '2020-05-01-18:00:00 PDT', 'date-to-epoch' => 1588381200, 'date-to' => '2020-05-01T18:00:00-07:00', 'date-from-local' => '2020-05-01-08:00:00 PDT', 'date-from' => '2020-05-01T08:00:00-07:00', 'forecast-string' => 'Chance Rain Showers', 'date-human-str' => 'Today', 'forecast-temp-F' => 65 } }; 2020/05/01 08:59:21 INFO $VAR1 = { '2020-05-01T18:00:00-07:00 to 2020-05-02T06:00:00-07:00' => { 'date-from' => '2020-05-01T18:00:00-07:00', 'date-from-local' => '2020-05-01-18:00:00 PDT', 'date-to' => '2020-05-02T06:00:00-07:00', 'date-to-epoch' => 1588424400, 'date-to-local' => '2020-05-02-06:00:00 PDT', 'date-span-hours' => '12', 'date-from-epoch' => 1588381200, 'forecast-temp-F' => 50, 'date-human-str' => 'Tonight', 'forecast-string' => 'Rain Showers' } }; 2020/05/01 08:59:21 INFO $VAR1 = { '2020-05-02T06:00:00-07:00 to 2020-05-02T18:00:00-07:00' => { 'date-from-local' => '2020-05-02-06:00:00 PDT', 'date-to' => '2020-05-02T18:00:00-07:00', 'date-from' => '2020-05-02T06:00:00-07:00', 'date-span-hours' => '12', 'date-to-local' => '2020-05-02-18:00:00 PDT', 'date-from-epoch' => 1588424400, 'date-to-epoch' => 1588467600, 'forecast-temp-F' => 60, 'forecast-string' => 'Rain Showers', 'date-human-str' => 'Saturday' } }; #### for (@responses){ [bliako]++; }