1use strict; 2use warnings; 3 4use lib 't/lib'; 5use T::RequireDateTime; 6 7use Test::More; 8use Test::Fatal; 9 10use DateTime::TimeZone; 11use Try::Tiny; 12 13my @names = DateTime::TimeZone::all_names(); 14cmp_ok( 15 scalar @names, '>', 100, 16 'at least 100 zones' 17); 18 19my %links = DateTime::TimeZone->links(); 20cmp_ok( 21 scalar keys %links, '>', 100, 22 'at least 100 links' 23); 24 25my $is_maintainer = -d '.git' || $ENV{RELEASE_TESTING} ? 1 : 0; 26 27foreach my $name (@names) { 28 my $resolved_name = $links{$name} || $name; 29 30 my $tz = DateTime::TimeZone->new( name => $name ); 31 isa_ok( $tz, 'DateTime::TimeZone' ); 32 33 is( $tz->name, $resolved_name, 'check ->name' ); 34 35 is( $tz->is_floating, 0, 'should not be floating' ); 36 is( $tz->is_utc, 0, 'should not be UTC' ) 37 unless $resolved_name eq 'UTC'; 38 39 # adding these tests makes the test suite take a _long_ time to 40 # finish, and it uses up lots of memory too. 41 if ($is_maintainer) { 42 my $dt; 43 is( 44 exception { $dt = DateTime->now( time_zone => $name ) }, 45 undef, 46 "Can call DateTime->now with $name" 47 ); 48 49 is( 50 exception { $dt->add( years => 50 ) }, 51 undef, 52 "Can add 50 years with $name" 53 ); 54 55 is( 56 exception { $dt->subtract( years => 400 ) }, 57 undef, 58 "Can subtract 400 years with $name" 59 ); 60 61 try { 62 $dt = DateTime->new( 63 year => 2000, month => 6, hour => 1, 64 time_zone => $name 65 ); 66 }; 67 is( $dt->hour, 1, 'make sure that local time is always respected' ); 68 69 try { 70 $dt = DateTime->new( 71 year => 2000, month => 12, hour => 1, 72 time_zone => $name 73 ); 74 }; 75 is( $dt->hour, 1, 'make sure that local time is always respected' ); 76 } 77} 78 79foreach my $name ( '0', 'Z', 'UTC' ) { 80 my $tz = DateTime::TimeZone->new( name => $name ); 81 isa_ok( $tz, 'DateTime::TimeZone' ); 82 83 is( $tz->name, 'UTC', 'name should be UTC' ); 84 85 is( $tz->is_floating, 0, 'should not be floating' ); 86 is( $tz->is_utc, 1, 'should be UTC' ); 87} 88 89my $tz = DateTime::TimeZone->new( name => 'America/Chicago' ); 90 91# These tests are odd since we're feeding UTC times into the time zone 92# object, which isn't what happens in real usage. But doing this 93# minimizes how much of DateTime.pm needs to work for these tests. 94{ 95 my $dt = DateTime->new( 96 year => 2001, 97 month => 9, 98 day => 10, 99 time_zone => 'UTC', 100 ); 101 is( $tz->offset_for_datetime($dt), -18000, 'offset should be -18000' ); 102 is( $tz->short_name_for_datetime($dt), 'CDT', 'name should be CDT' ); 103} 104 105{ 106 my $dt = DateTime->new( 107 year => 2001, 108 month => 10, 109 day => 29, 110 time_zone => 'UTC', 111 ); 112 is( $tz->offset_for_datetime($dt), -21600, 'offset should be -21600' ); 113 is( $tz->short_name_for_datetime($dt), 'CST', 'name should be CST' ); 114} 115 116{ 117 118 # check that generation works properly 119 my $dt = DateTime->new( 120 year => 2200, 121 month => 11, 122 day => 2, 123 time_zone => 'UTC', 124 ); 125 is( 126 $tz->offset_for_datetime($dt), -18000, 127 'generated offset should be -1800' 128 ); 129 is( 130 $tz->short_name_for_datetime($dt), 'CDT', 131 'generated name should be CDT' 132 ); 133} 134 135{ 136 137 # check that generation works properly 138 my $dt = DateTime->new( 139 year => 2200, 140 month => 11, 141 day => 3, 142 time_zone => 'UTC', 143 ); 144 is( 145 $tz->offset_for_datetime($dt), -21600, 146 'generated offset should be -21600' 147 ); 148 is( 149 $tz->short_name_for_datetime($dt), 'CST', 150 'generated name should be CST' 151 ); 152} 153 154{ 155 my $dt = DateTime->new( 156 year => 1944, 157 month => 10, 158 day => 29, 159 time_zone => 'UTC', 160 ); 161 is( $tz->offset_for_datetime($dt), -18000, 'offset should be -18000' ); 162 is( $tz->short_name_for_datetime($dt), 'CWT', 'name should be CWT' ); 163} 164 165{ 166 my $dt = DateTime->new( 167 year => 1936, 168 month => 3, 169 day => 2, 170 time_zone => 'UTC', 171 ); 172 173 is( $tz->offset_for_datetime($dt), -18000, 'offset should be -18000' ); 174 is( $tz->short_name_for_datetime($dt), 'EST', 'name should be EST' ); 175} 176 177{ 178 my $dt = DateTime->new( 179 year => 1883, 180 month => 1, 181 day => 29, 182 time_zone => 'UTC', 183 ); 184 185 is( $tz->offset_for_datetime($dt), -21036, 'offset should be -21036' ); 186 is( $tz->short_name_for_datetime($dt), 'LMT', 'name should be LMT' ); 187} 188 189{ 190 { 191 192 package TestHack; 193 194 sub new { bless {}, shift } 195 196 # UTC RD secs == 63518486401 197 sub utc_rd_values { ( 735167, 57601 ) } 198 } 199 200 # This is to check a bug in DT::TZ::_span_for_datetime, where it 201 # was always looking at the LOCAL_END of the current max_span. 202 # 203 # Australia/Sydney's max_span (before generation) has a LOCAL_END 204 # of 63518522400 and UTC_END of 63518486400. The values above 205 # create a utc_rd_seconds value that is after the UTC_END but 206 # before the LOCAL_END. 207 my $dt = DateTime->from_object( object => TestHack->new ); 208 209 is( 210 exception { 211 $dt->set_time_zone('UTC')->set_time_zone('Australia/Sydney') 212 }, 213 undef, 214 'should be able to set time zone without error' 215 ); 216 217 ok( $dt->is_dst, 'is_dst should be true' ); 218} 219 220{ 221 my $offset_tz = DateTime::TimeZone->new( name => '-0100' ); 222 ok( 223 !$offset_tz->is_olson, 224 'is_olson is false for offset only time zone' 225 ); 226} 227 228{ 229 230 # bug when creating new datetime for year just after time zone's 231 # max year 232 my $la_tz = DateTime::TimeZone->new( name => 'America/Los_Angeles' ); 233 234 my $dt = try { 235 DateTime->new( 236 year => $la_tz->{max_year} + 1, 237 month => 5, 238 day => 20, 239 time_zone => $la_tz 240 ); 241 }; 242 ok( $dt, 'was able to create datetime object' ); 243} 244 245done_testing(); 246