1 #$Header: /home/cvs/cvsroot/freeside/rt/lib/RT/Date.pm,v 1.1 2002-08-12 06:17:07 ivan Exp $
2 # (c) 1996-2000 Jesse Vincent <jesse@fsck.com>
3 # This software is redistributable under the terms of the GNU GPL
7 RT::Date - a simple Object Oriented date.
15 RT Date is a simple Date Object designed to be speedy and easy for RT to use
17 The fact that it assumes that a time of 0 means "never" is probably a bug.
21 ok (require RT::Date);
32 use vars qw($MINUTE $HOUR $DAY $WEEK $MONTH $YEAR);
45 my $class = ref($proto) || $proto;
47 bless ($self, $class);
58 takes a param hash with the fields 'Format' and 'Value'
60 if $args->{'Format'} is 'unix', takes the number of seconds since the epoch
62 If $args->{'Format'} is ISO, tries to parse an ISO date.
64 If $args->{'Format'} is 'unknown', require Date::Parse and make it figure things
65 out. This is a heavyweight operation that should never be called from within
66 RT's core. But it's really useful for something like the textbox date entry
67 where we let the user do whatever they want.
69 If $args->{'Value'} is 0, assumes you mean never.
76 my %args = ( Format => 'unix',
79 if (($args{'Value'} =~ /^\d*$/) and ($args{'Value'} == 0)) {
81 return($self->Unix());
84 if ($args{'Format'} =~ /^unix$/i) {
85 $self->Unix($args{'Value'});
88 elsif ($args{'Format'} =~ /^(sql|datemanip|iso)$/i) {
90 if (($args{'Value'} =~ /^(\d{4}?)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) ||
91 ($args{'Value'} =~ /^(\d{4}?)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/) ||
92 ($args{'Value'} =~ /^(\d{4}?)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\+00$/) ||
93 ($args{'Value'} =~ /^(\d{4}?)(\d\d)(\d\d)(\d\d):(\d\d):(\d\d)$/)) {
102 #timegm expects month as 0->11
105 #now that we've parsed it, deal with the case where everything
111 #Dateamnip strings aren't in GMT.
112 if ($args{'Format'} =~ /^datemanip$/i) {
113 $self->Unix(timelocal($sec,$min,$hours,$mday,$mon,$year));
115 #ISO and SQL dates are in GMT
117 $self->Unix(timegm($sec,$min,$hours,$mday,$mon,$year));
120 $self->Unix(-1) unless $self->Unix;
126 $RT::Logger->debug( "Couldn't parse date $args{'Value'} as a $args{'Format'}");
130 elsif ($args{'Format'} =~ /^unknown$/i) {
132 #Convert it to an ISO format string
134 my $date = Date::Parse::str2time($args{'Value'});
136 #This date has now been set to a date in the _local_ timezone.
137 #since ISO dates are known to be in GMT (for RT's purposes);
139 $RT::Logger->debug("RT::Date used date::parse to make ".$args{'Value'} . " $date\n");
142 return ($self->Set( Format => 'unix', Value => "$date"));
145 die "Unknown Date format: ".$args{'Format'}."\n";
148 return($self->Unix());
153 # {{{ sub SetToMidnight
157 Sets the date to midnight (at the beginning of the day) GMT
158 Returns the unixtime at midnight.
166 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($self->Unix);
167 $self->Unix(timegm (0,0,0,$mday,$mon,$year,$wday,$yday));
169 return ($self->Unix);
180 return($self->Set(Format => 'unix', Value => time))
188 Takes either an RT::Date object or the date in unixtime format as a string
190 Returns the differnce between $self and that time as a number of seconds
198 if (ref($other) eq 'RT::Date') {
201 return ($self->Unix - $other);
205 # {{{ sub DiffAsString
207 =head2 sub DiffAsString
209 Takes either an RT::Date object or the date in unixtime format as a string
211 Returns the differnce between $self and that time as a number of seconds as
212 as string fit for human consumption
224 if ($self->Unix < 1) {
227 my $diff = $self->Diff($other);
229 return ($self->DurationAsString($diff));
233 # {{{ sub DurationAsString
235 =head2 DurationAsString
237 Takes a number of seconds. returns a string describing that duration
241 sub DurationAsString{
244 my $duration = shift;
248 $negative = 'ago' if ($duration < 0);
250 $duration = abs($duration);
252 if($duration < $MINUTE) {
255 } elsif($duration < (2 * $HOUR)) {
256 $s = int($duration/$MINUTE);
258 } elsif($duration < (2 * $DAY)) {
259 $s = int($duration/$HOUR);
261 } elsif($duration < (2 * $WEEK)) {
262 $s = int($duration/$DAY);
264 } elsif($duration < (2 * $MONTH)) {
265 $s = int($duration/$WEEK);
267 } elsif($duration < $YEAR) {
268 $s = int($duration/$MONTH);
271 $s = int($duration/$YEAR);
275 return ("$s $string $negative");
280 # {{{ sub AgeAsString
282 =head2 sub AgeAsString
286 Returns a string that's the differnce between the time in the object and now
292 return ($self->DiffAsString(time));
300 Returns the object\'s time as a string with the current timezone.
306 return ("Not set") if ($self->Unix <= 0);
308 return (scalar(localtime($self->Unix)));
314 =head2 sub AddSeconds
316 Takes a number of seconds as a string
326 $self->Set(Format => 'unix', Value => ($self->Unix + $delta));
328 return ($self->Unix);
339 Adds 24 hours * $DAYS to the current time
346 $self->AddSeconds($days * $DAY);
356 Adds 24 hours to the current time
362 $self->AddSeconds($DAY);
370 =head2 sub Unix [unixtime]
372 Optionally takes a date in unix seconds since the epoch format.
373 Returns the number of seconds since the epoch
380 $self->{'time'} = shift if (@_);
382 return ($self->{'time'});
392 Returns the object's date in ISO format
398 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst, $date) ;
400 return ('1970-01-01 00:00:00') if ($self->Unix == -1);
403 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($self->Unix);
407 #the month needs incrementing, as gmtime returns 0-11
410 $date = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year,$mon,$mday, $hour,$min,$sec);
418 # {{{ sub LocalTimezone
421 Returns the current timezone. For now, draws off a system timezone, RT::Timezone. Eventually, this may
422 pull from a 'Timezone' attribute of the CurrentUser
429 return ($RT::Timezone);