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