1=head1 NAME 2 3Date::Handler - Easy but complete date object (1.1) 4 5=head1 SYNOPSIS 6 7 use Date::Handler; 8 9 my $date = new Date::Handler({ date => time, time_zone => 'Europe/Paris', locale => 'french'}); 10 my $date = new Date::Handler({ date => [2001,04,12,03,01,55], time_zone => 'EST', }); 11 my $date = new Date::Handler({ date => { 12 year => 2001, 13 month => 4, 14 day => 12, 15 hour => 3, 16 min => 1, 17 sec => 55, 18 }, 19 time_zone => 'America/Los_Angeles', 20 locale => 'en_US.ISO8859-15', 21 }); 22 23 print $date; 24 print "$date"; 25 print $date->AllInfo(); 26 27 $date->new() Constructor 28 $date->Year() 2001 29 $date->Month() 1..12 30 $date->Day() 1..31 31 $date->Hour() 0..23 32 $date->Min() 0..59 33 $date->Sec() 0..59 34 $date->Epoch($epoch) Seconds since epoch (GMT) 35 $date->TimeZone() America/Montreal,EST,PST and so on 36 $date->Locale() french, en_US.ISO8859-15, fr_FR.ISO8859-15, spanish and so on 37 $date->SetLocale(locale) Set the locale to the argument, returns locale or undef. 38 $date->LocaleRealName() Current locale's real name on the system 39 $date->TimeZoneName() EST, PST and so on 40 $date->LocalTime() localtime of the object's epoch 41 $date->TimeFormat($format_string) strftime 42 $date->GmtTime() gmtime of object's epoch 43 $date->UtcTime() same as GmtTime() 44 $date->GmtOffset() Offset of object's TZ in seconds 45 $date->MonthName() April 46 $date->WeekDay() 1..7 (1 monday) 47 $date->WeekDayName() Wednesday 48 $date->FirstWeekDayOfMonth() 1..7 49 $date->WeekOfMonth() 1..4 50 $date->DaysInMonth() 31,30,29,28 depending on month and year. 51 $date->IsLeapYear() 1 if true, 0 if false 52 $date->DayLightSavings() 1 if true, 0 if false 53 $date->DayOfYear() Return the day of the year 54 $date->DaysInYear() Returns the number of days in the year. 55 $date->DaysLeftInYear() Returns the number of days remaining in the year 56 $date->Array2Epoch([]) Transfer [y,m,d,h,mm,ss] to epoch time 57 $date->AsScalar () Same as TimeFormat("%A, %B%e %Y %R (%Z)") 58 $date->AsNumber() same as Epoch() 59 $date->AsArray() Returns [y,m,d,h,mm,ss] 60 $date->AsHash() Returns { year => y, month => m, day => d, hour => h, min => mm, sec => ss } 61 $date->AllInfo() Returns a string containing all of the Object's related information. 62 63 64 my $delta = new Date::Handler::Delta([3,1,10,2,5,5]); 65 my $delta = new Date::Handler::Delta({ 66 years => 3, 67 months => 1, 68 days => 10, 69 hours => 2, 70 minutes => 5, 71 seconds => 5, 72 }); 73 74 $delta->new (More information in perldoc Date::Handler::Delta) 75 $delta->Months() Number of months in delta 76 $delta->Seconds() Number of seconds in delta 77 $delta->AsScalar() "%d months and %d seconds" 78 $delta->AsNumber() "%d-%d-%d" 79 $delta->AsArray() [y,m,ss] 80 $delta->AsHash() { months => m, seconds => ss } 81 82 $date + $delta = Date::Handler 83 $date - $delta = Date::Handler 84 $date - $date2 = Date::Handler::Delta 85 $date + n = (+n seconds) 86 $date - n = (-n seconds) 87 88 $delta + $delta = Date::Handler::Delta 89 $delta - $delta = Date::Handler::Delta 90 $delta * n = Date::Handler::Delta 91 $delta / n = Date::Handler::Delta 92 $delta + n = (+n seconds) 93 $delta - n = (-n seconds) 94 95 96 my $range = Date::Handler::Range->new({ 97 date => $date, 98 delta => $delta, 99 }); 100 my $range = Date::Handler::Range->new({ 101 date => [2001,06,08,2,00,00], 102 delta => [0,0,1,0,0], 103 }); 104 105 $range->new (More info in perldoc Date::Handler::Range) 106 $range->Direction() Specifies the direction of a range ('FORWARDS' || 'BACKWARDS') 107 $range->StartDate() Start Date::Handler object for this range and direction 108 $range->EndDate() End Date::Handler object for this range and direction 109 $range->Overlaps($range2) Returns true if range overlaps range2. undef otherwise. 110 111 112=head1 DESCRIPTION 113 114Date::Handler is a container for dates that holds all the methods to transform itself 115from Timezone to Timezone and format itself. This module idea comes from an original version 116written by dLux (Szab�, Bal�zs) <dlux@kapu.hu> in his module Class::Date. 117 118Date::Handler is implemented in pure Perl using POSIX modules, it encapsulates the environnement variable 119TZ for it's time zone management so you don't have to play with it externally in the implementation. Date::Handler 120also supports localisation using POSIX where available. 121 122It uses operator overloading and Delta date objects to calculates time differences. 123 124=head1 IMPLEMENTATION 125 126Using the Date::Handler is simple. 127 128=head2 Creating the absolute Date::Handler 129 130The new() constructor receives only one argument as a hashref: 131 132 my $date = new Date::Handler({ 133 date => time, 134 time_zone => 'Japan', 135 }); 136 137 138 my $date = new Date::Handler({ 139 date => time(), 140 time_zone => 'America/Los_Angeles', 141 locale => 'spanish', 142 }); 143 144The 'date' key of this argument can be either: 145 146=over 3 147 148=item * Epoch time 149 150=item * Anonymous array of the form: [y,m,d,h,mm,ss] 151 152=item * A hashref of the form : { year => y,month => m, day => d, hour => h, min => mm, sec => ss } 153 154=back 155 156The items in the array (or hash) of the 'date' key should follow these rules: 157 158=over 3 159 160=item * year - The year number 161 162=item * mon - The number of months since January, in the range 1 to 12. 163 164=item * day - The day of the month, in the range 1 to 31. 165 166=item * hour - The number of hours past midnight, in the range 0 to 23. 167 168=item * min - The number of minutes after the hour, in the range 0 to 59. 169 170=item * sec - The number of seconds after the minute, normally in the range 0 to 59. 171 172=back 173 174The optional 'time_zone' key represents the time zone name this date is considered in. i.e. Africa/Dakar, EST, PST, EDT 175 176The optional 'locale' key represents the locale used to represent this date. i.e. spanish, japananese, de_DE.ISO8859-15 , fr_FR.ISO8859-15 177 178You can also pass an 'intuitive_day' key to the constructor. This is described in the 179"USING INTUITIVE MONTH CALCULATIONS" section. 180 181=head2 Accessors 182 183You can access the data inside the object using any of the provided methods. 184These methods are detailed in the SYNOPSIS up above. 185 186 187=head2 Modifying the object 188 189A created Date::Handler can be modified on the fly by many ways: 190 191=over 3 192 193=item * Changing the time_zone of the object using TimeZone() 194 195=item * Changing the object's locale on the fly using SetLocale() 196 197=item * Changing the internal date of the object using Epoch() 198 199=item * By using operators in combination with Date::Handler::Delta objects 200 201 202=back 203 204Examples: 205 206 #Start off with a basic object for NOW. 207 my $date = new Date::Handler({ date => time }); 208 209 #Go through the time zones... 210 $date->TimeZone('Asia/Tokyo'); 211 print "Time in tokyo: ".$date->LocalTime()."\n"; 212 $date->Epoch(time); 213 $date->TimeZone('America/Montreal'); 214 print "Time in Montreal: ".$date->LocalTime()."\n"; 215 $date->TimeZone('GMT'); 216 print "Greenwich Mean Time: ".$date->LocalTime()."\n"; 217 218 # Go through some locales... 219 220 $date->SetLocale('french'); 221 print "Time in ".$date->Locale().": ".$date."\n"; 222 $date->SetLocale('deutsch'); 223 print "Time in ".$date->Locale().": ".$date."\n"; 224 $date->SetLocale('spanish'); 225 print "Time in ".$date->Locale().": ".$date."\n"; 226 227 228=head2 Operator overload special cases 229 230The Date::Handler overloaded operator have special cases. Refer to the 231SYNOPSIS to get a description of each overloaded operator's behaviour. 232 233One special case of the overload is when adding an integer 'n' to a Date::Handler's reference. This is treated as if 'n' was in seconds. Same thing for substraction. 234 235Example Uses of the overload: 236 237 my $date = new Date::Handler({ date => 238 { 239 year => 2001, 240 month => 5, 241 day => 14, 242 hour => 5, 243 min => 0, 244 sec => 0, 245 }}); 246 #Quoted string overload 247 print "Current date is $date\n"; 248 249 my $delta = new Date::Handler::Delta({ days => 5, }); 250 251 #'+' overload, now, $date is 5 days in the future. 252 $date += $delta; 253 254 #Small clock. Not too accurate, but still ;) 255 while(1) 256 { 257 #Add one second to the date. (same as $date + 1) 258 $date++; 259 print "$date\n"; 260 sleep(1); 261 } 262 263 264 265 266=head1 INHERITANCE 267 268A useful way of using Date::Handler in your code is to implement that a class 269that ISA Date::Handler. This way you can overload methods through the inheritance 270tree and change the object's behaviour to your needs. 271 272Here is a small example of an overloaded class that specifies a default 273timezone different than the machine's timezone. 274 275 #!/usr/bin/perl 276 package My::Date::Handler; 277 278 use strict; 279 use vars qw(@ISA $VERSION); 280 281 use Date::Handler; 282 @ISA = qw(Date::Handler); 283 284 use constant DEFAULT_TIMEZONE => 'Europe/Moscow'; 285 use consant DEFAULT_LOCALE => 'russian'; 286 287 sub TimeZone 288 { 289 my ($self) = @_; 290 291 my $time_zone = $self->SUPER::TimeZone(@_); 292 293 return $time_zone if defined $time_zone; 294 295 return $self->DEFAULT_TIMEZONE(); 296 } 297 298 1; 299 __END__ 300 301=head1 USING INTUITIVE MONTH CALCULATIONS (off by default) 302 303Date::Handler contains a feature by witch a date handler object can use intuitive 304month calculation. This means that Date::Handler will compensate for month 305overflows during delta operations. 306 307For example, if you have a date handler that is 2002/01/30, and you add to it a delta 308of 1 month, standard Date::Handler object will give you a new object that is 2002/03/02. 309This is because POSIX will compensate for the month overflow and add 2 days to the date 310because February does not have a 29 or 30th in 2002. Date::Handler can compensate for 311that by using the INTUITIVE_MONTH_CALCULATIONS constant. (this is turned off by default). 312 313This constant can be turned on during overloading (inheritance): 314 315 use constant INTUITIVE_MONTH_CALCULATIONS => 1; 316 317Turning this constant on will tell Date::Handler to follow track of month overflow during 318operations. This will make it so that adding a month to 2002/01/30 will bring you to 3192002/02/28. Adding another month to this will bring you (with intuition) to 2002/03/30, 320because Date::Handler keeps track of the "intuitive" day of the month. 321 322Using INTUITIVE_MONTH_CALCULATIONS will also make it possible to pass an "intuitive_day" 323key to the new() constructor in order to simulate a previous addition. 324 325 i.e. 326 327 my $date = Date::Handler->new({ 328 date => [2002,02,28,1,0,0,0], 329 time_zone => 'America/Montreal', 330 intuitive_day => '30', 331 }); 332 333 my $onemonth = Date::Handler::Delta->new([0,1,0,0,0,0]); 334 335 print ($date + $onemonth)."\n"; 336 337In this example, the start date of 2002/02/28 with intuitive_day set to 30 will make it 338so that adding 1 month to the date will bring us to march 30th. Note that INTUITIVE_MONTH_CALCULATIONS will only affect month/day calculations and no time modifications will be applied. 339 340=head1 USING INTUITIVE_DST_ADJUSTMENTS (off by default) 341 342Date::Handler provides a facility called INTUITIVE_DST_ADJUSTMENTS. This is implemented via an 343inherited constant, like the other options above. When INTUITIVE_DST_ADJUSTMENTS are turned on, 344Date::Handler will compensate for day light savings changes. For example, 2002/04/07 1AM + 1 day 345would give you 2002/04/08 1AM instead of 2AM. Note that INTUITIVE_DST_ADJUSTMENTS will not apply 346this compensation when the exact "turn over" date/time is detected. For example, 2002/04/06 2AM 347+ 1 day would give you 2002/04/07 3AM because we don't compensate for this specific case. 348 349=head1 USING INTUITIVE_TIME_CALCULATIONS (off by default) 350 351Date::Handler provides yet another facility to add intuitive date calculations. By using 352INTUITIVE_TIME_CALCULATIONS (via inherited constant), Date::Handler will "remember" that it 353compensated for a DST adjustment and try to compensate for it. 354 355For example, 2002/04/06 2AM + 1day would give you 2002/04/07 3AM. Adding a day to this date 356under INTUITIVE_TIME_CALCULATIONS would give you 2002/04/08 2AM because Date::Handler remembers 357it compensated for day light savings. 358 359Combining INTUITIVE_DST_ADJUSTMENTS, INTUITIVE_MONTH_CALCULATIONS and INTUITIVE_TIME_CALCULATIONS 360will give a behaviour closer to the way humans expect the module to react. 361 362This can be very useful to make date calculations a little more "humanized". 363 364The intuitive "hour" can be faked by passing it to the new() constructor: 365 366 package MyDateHandler; 367 368 use strict; 369 use base qw(Date::Handler); 370 371 use constant INTUITIVE_DST_ADJUSTMENTS => 1; 372 use constant INTUITIVE_TIME_CALCULATIONS => 1; 373 374 1; 375 376 377then: 378 379 my $date = MyDateHandler->new({ 380 date => [2002,04,08,5,0,0], 381 time_zone => 'America/Montreal', 382 intuitive_hour => 2, 383 }); 384 385=head1 NOTES ON TIME ZONES, LOCALISATION AND FORMATTING 386 387Date::Handler supports locales using POSIX setlocale() functions. The allowed values for the locale 388are listed (on most unix system) using the `locale -a` command. The Date::Handler defaults to "en_US.ISO8859-15" for 389it's locale when no locale are passed to the constructor. The constant DEFAULT_LOCALE can be overloaded 390to change this behaviour. Special note that the locales "english" and "en" are not implemented on most linux 391(Red Hat here) systems. You need to use the locale en_US.ISO8859-15, en_GB.ISO8859-15 etc etc. 392 393Date::Handler supports time zones using POSIX tzset() and tzname() functions. The allowed values for the 394time_zone key are listed (on linux systems) by look at the /usr/share/zoneinfo directory. The Date::Handler 395default to "GMT" for it's time zone when to time_zone key are passed to the constructor. The constant DEFAULT_TIME_ZONE 396can be overloaded to change this behaviour. 397 398Date::Handler's formatting is provided by POSIX's strfmtime() function. The allowed parameters to the TimeFormat() 399method can be listed (on most unix system) using `man strftime`. By default, Date::Handler uses the format 400string '%c' to represent itself in most cases. The constant DEFAULT_FORMAT_STRING can be overloaded to change 401this behaviour. 402 403=head1 OTHER DATE::HANDLER MODULES 404 405Here is a brief description of the other modules in this package. 406 407=head2 Using Date::Handler::Delta objects 408 409To go forward or backward in time with a date object, you can use 410the Date::Handler::Delta objects. These objects represent a time lapse 411represented in months and seconds. Since Date::Handler uses 412operator overloading, you can 'apply' a Delta object on an absolute date 413simply by using '+' and '-'. 414 415Example: 416 417 #A Delta of 1 year. 418 my $delta = new Date::Handler::Delta([1,0,0,0,0,0]); 419 420 my $date = new Date::Handler({ date => time } ); 421 422 #$newdate is now one year in the furure. 423 my $newdate = $date+$delta; 424 425 426Refer to the Date::Handler::Delta(1) documentation for more on Deltas. 427 428 429=head2 Using Date::Handler::Range objects 430 431Range objects are used to define a time range using a start date and a delta object. 432Can be useful to calculate recurrences of events and event overlap. 433 434Example: 435 436 A simple range for an event of 3 days: 437 438 my $range = Date::Handler::Range->new({ 439 date => Date::Handler->new({ date => time() }), 440 delta => Date::Handler::Delta->new([0,0,3,0,0,0]), 441 }); 442 443 print "This event starts on ".$range->StartDate()." and end on ".$range->EndDate()."\n"; 444 445See perldoc Date::Handler::Range(1) for more information on how to use Date::Handler::Range objects. 446 447 448=head1 BUGS (known) 449 450Dates after 2038 are not handled by this module yet. (POSIX) 451 452Dates before 1970 are not handled by this module. (POSIX) 453 454If you find bugs with this module, do not hesitate to contact the author. 455Your comments and rants are welcomed :) 456 457 458=head1 SUPPORT, CVS AND BLEEDING VERSIONS 459 460For the latest developments,changes files, history, CVS access and more, please visit: 461 462http://labs.turbulent.ca/ 463 464Please, if you use this module in a project, let me know! 465 466Commercial support for this module is available, please contact me for more info! 467 468=head1 TODO 469 470Add support for dynamic locale using perllocales functions. This will plugin directly with the use of strftime in the Date::Handler and provide locales. 471 472Add a list of supported timezones in the Constants class.Just didnt around 473to do it yet :) Feel free :) If you have patches, recommendations or suggestions on this module, please come forward :) 474 475=head1 COPYRIGHT 476 477Copyright(c) 2001 Benoit Beausejour <bbeausej@pobox.com> 478 479All rights reserved. This program is free software; you can redistribute it and/or modify it under the same 480terms as Perl itself. 481 482Portions Copyright (c) Philippe M. Chiasson <gozer@cpan.org> 483 484Portions Copyright (c) Szab�, Bal�zs <dlux@kapu.hu> 485 486Portions Copyright (c) Larry Rosler 487 488 489=head1 AUTHOR 490 491Benoit Beausejour <bbeausej@pobox.com> 492 493=head1 CONTRIBUTORS 494 495=over 3 496 497=item * Ron Savage <ron@savage.net.au> 498 499=item * Roland Rauch <roland@rauch.com> 500 501=item * Patrick Bradley <peanut@burstofindifference.com> 502 503=item * Phillippe M. Chiasson <gozer@cpan.org> 504 505=item * Jamie Letual <jamie@letual.net> 506 507=item * Ethan Joffe <ethan@namimedia.com> 508 509=item * Mathew Robertson <mathew.robertson@redsheriff.com> 510 511=item * Sivaguru Sankaridurg <uc_regents@yahoo.com> 512 513=back 514 515=head1 SEE ALSO 516 517Class::Date(1). 518Time::Object(1). 519Date::Calc(1). 520perl(1). 521 522=cut 523 524