2018-05-25
OpenWeatherMapのAPIで東京の天気を取得して、翌日の最高気温、最低気温を摂氏で表示する。
■メインコード
package Indicate_TEMP; use Exporter 'import'; our @EXPORT = qw/get_date_temp get_api_data return_temp print_temp/; our $VERSION = "0.0.1"; use LWP::UserAgent; use strict; use warnings; use utf8; use Encode; use JSON::XS 'decode_json'; use Data::Dumper; use DateTime; #API Key、URLの代入。 my $date = $ARGV[0]; &get_date_temp($date); sub get_date_temp{ my ($date) = @_; if (!$date){ my $dt = DateTime->now(time_zone => 'Asia/Tokyo'); $dt->add( days => 1 ); $date = $dt->ymd('-'); } unless ($date =~ /\d{4}-\d{2}-\d{2}/){ print "Please enter the correct date format.\n"; return undef; } my $api_data = &get_api_data; my $temp_ref = &return_temp($api_data, $date); &print_temp($temp_ref, $date); return 1; } #apiからのデータの取得処理を行うサブルーチンを作成。 sub get_api_data{ my $api_key = 'ed0e5aec8d17204480f7bde57279e1af'; my $base_url = 'http://api.openweathermap.org/data/2.5/forecast'; my $ua = LWP::UserAgent->new; my $res = $ua->get( "$base_url?q=tokyo,jp&appid=$api_key&units=metric" # http://api.openweathermap.org/data/2.5/forecast?q=tokyo,jp&appid=ed0e5aec8d17204480f7bde57279e1af&units=metric ); my $file = "{}"; if ($res->is_success) { $file = $res->content; } else { print "Failed to acquire web data.\n"; return undef; } my $api_data = decode_json($file); return $api_data; } #指定された日の12時の気温、最高気温、最低気温が入ったハッシュリファレンスを返すためのサブルーチンを作成。 sub return_temp{ my ($api_data, $date) = @_; unless (defined($api_data)){ print "API data is not defined.\n"; return undef; } my $date_12pm = $date." 12:00:00"; my $key; #12時の気温の取得。 my $temp_12 = 'undef'; foreach $key(keys $api_data->{'list'}){ my $dt_txt_phr = $api_data->{'list'}->[$key]->{'dt_txt'}; if ($dt_txt_phr) { if ($dt_txt_phr =~ /$date_12pm/){ $temp_12 = $api_data->{'list'}->[$key]->{'main'}->{'temp'}; } } } #最高気温と最低気温の取得。 my $max; my $min; my $temp_max; my $temp_min; foreach $key (keys $api_data->{'list'}) { my $dt_txt_phr = $api_data->{'list'}->[$key]->{'dt_txt'}; if ($dt_txt_phr) { if ($dt_txt_phr =~ /$date/){ $temp_max = $api_data->{'list'}->[$key]->{'main'}->{'temp_max'}; $temp_min = $api_data->{'list'}->[$key]->{'main'}->{'temp_min'}; unless (defined($max)){ $max = $temp_max; } unless (defined($min)){ $min = $temp_min; } if ($max < $temp_max) { $max = $temp_max; } if ($min > $temp_min) { $min = $temp_min; } } } } unless (defined($max)) { $max = 'undef'; } unless (defined($min)) { $min = 'undef'; } my %temp = ("12pm_temp" => "$temp_12", "temp_max" => "$max", "temp_min" => "$min") ; #print %temp; if (%temp){ return \%temp; } else { return undef; } } #指定された日の12時の気温、最高気温、最低気温をprintするためのサブルーチンを作成。 sub print_temp{ my ($temp_ref, $date) = @_; my $str_1 = sprintf (qq/%sの12:00の気温は%s°cです。\n/, $date, $temp_ref->{"12pm_temp"}); my $str_2 = sprintf (qq/%sの最高気温は%s°cです。\n/, $date, $temp_ref->{"temp_max"}); my $str_3 = sprintf (qq/%sの最低気温は%s°cです。\n/, $date, $temp_ref->{"temp_min"}); my $enc_str_1 = encode('utf-8', $str_1); my $enc_str_2 = encode('utf-8', $str_2); my $enc_str_3 = encode('utf-8', $str_3); print $enc_str_1; print $enc_str_2; print $enc_str_3; } 1;
■テストコード
use strict; use warnings; use JSON::XS 'decode_json'; use Test::More; BEGIN { use_ok('Indicate_TEMP') || BAIL_OUT(); } diag("Testing Indicate_TEMP $Indicate_TEMP::VERSION, Perl $], $^X"); # サブルーチンが定義されているかのテスト。 ok( defined &Indicate_TEMP::get_date_temp, 'Indicate_TEMP::get_date_temp is defined' ); ok( defined &Indicate_TEMP::get_api_data, 'Indicate_TEMP::get_api_data is defined' ); ok( defined &Indicate_TEMP::return_temp, 'Indicate_TEMP::return_temp is defined' ); ok( defined &Indicate_TEMP::print_temp, 'Indicate_TEMP::print_temp is defined' ); { use Indicate_TEMP; #関数get_date_tempのテスト。 { my $api_data = {'list' => [ { 'dt_txt' => '2018-05-24 12:00:00', 'main' => { 'temp_max' => '18.74', 'temp' => '18.74', 'temp_min' => '17.61', } } ] }; my $date = "2018-05-24"; is( get_date_temp($date), 1); $date = "22222222222222"; is( get_date_temp($date), undef); $date = (); is( get_date_temp($date), 1); } #関数get_api_dataのテスト { my $api_data = {'list' => [ { 'dt_txt' => '2018-05-24 12:00:00', 'main' => { 'temp_max' => '18.74', 'temp' => '18.74', 'temp_min' => '17.61', } } ] }; ok( get_api_data, $api_data); my $file = ""; ok( get_api_data, undef); my $api_key = ""; ok( get_api_data, undef); my $base_url = ""; ok( get_api_data, undef); } #関数return_tempのテスト { my $api_data = {'list' => [ { 'dt_txt' => '2018-05-24 12:00:00', 'main' => { 'temp_max' => '18.74', 'temp' => '18.74', 'temp_min' => '17.61', } } ] }; my $date = "2018-05-24"; $api_data = undef; is( return_temp($api_data, $date), undef); } } done_testing;