1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
6 # <sales@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # 02110-1301 or visit their web page on the internet at
27 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
30 # CONTRIBUTION SUBMISSION POLICY:
32 # (The following paragraph is not intended to limit the rights granted
33 # to you to modify and distribute this software under the terms of
34 # the GNU General Public License and is only of importance to you if
35 # you choose to contribute your changes and enhancements to the
36 # community by submitting them to Best Practical Solutions, LLC.)
38 # By intentionally submitting any modifications, corrections or
39 # derivatives to this work, or any other work intended for use with
40 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 # you are the copyright holder for those contributions and you grant
42 # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43 # royalty-free, perpetual, license to use, copy, create derivative
44 # works based on those contributions, and sublicense and distribute
45 # those contributions and any derivatives thereof.
47 # END BPS TAGGED BLOCK }}}
51 RT::Date - a simple Object Oriented date.
59 RT Date is a simple Date Object designed to be speedy and easy for RT to use
61 The fact that it assumes that a time of 0 means "never" is probably a bug.
75 use base qw/RT::Base/;
81 use vars qw($MINUTE $HOUR $DAY $WEEK $MONTH $YEAR);
87 $MONTH = 30.4375 * $DAY;
88 $YEAR = 365.25 * $DAY;
105 our @DAYS_OF_WEEK = (
116 'DefaultFormat', # loc
122 'LocalizedDateTime', # loc
127 Object constructor takes one argument C<RT::CurrentUser> object.
133 my $class = ref($proto) || $proto;
135 bless ($self, $class);
136 $self->CurrentUser(@_);
143 Takes a param hash with the fields C<Format>, C<Value> and C<Timezone>.
145 If $args->{'Format'} is 'unix', takes the number of seconds since the epoch.
147 If $args->{'Format'} is ISO, tries to parse an ISO date.
149 If $args->{'Format'} is 'unknown', require Time::ParseDate and make it figure
150 things out. This is a heavyweight operation that should never be called from
151 within RT's core. But it's really useful for something like the textbox date
152 entry where we let the user do whatever they want.
154 If $args->{'Value'} is 0, assumes you mean never.
167 return $self->Unix(0) unless $args{'Value'} && $args{'Value'} =~ /\S/;
169 my $format = lc $args{'Format'};
171 if ( $format eq 'unix' ) {
172 return $self->Unix( $args{'Value'} );
175 ($format eq 'sql' || $format eq 'iso')
176 && $args{'Value'} =~ /^(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/
179 my $u = eval { Time::Local::timegm($6, $5, $4, $3, $2-1, $1) } || 0;
180 $RT::Logger->warning("Invalid date $args{'Value'}: $@") if $@ && !$u;
181 return $self->Unix( $u > 0 ? $u : 0 );
183 elsif ( $format =~ /^(sql|datemanip|iso)$/ ) {
184 $args{'Value'} =~ s!/!-!g;
186 if ( ( $args{'Value'} =~ /^(\d{4})?(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/ )
187 || ( $args{'Value'} =~ /^(\d{4})?(\d\d)(\d\d)(\d\d):(\d\d):(\d\d)$/ )
188 || ( $args{'Value'} =~ /^(?:(\d{4})-)?(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/ )
189 || ( $args{'Value'} =~ /^(?:(\d{4})-)?(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)\+00$/ )
192 my ($year, $mon, $mday, $hours, $min, $sec) = ($1, $2, $3, $4, $5, $6);
194 # use current year if string has no value
195 $year ||= (localtime time)[5] + 1900;
197 #timegm expects month as 0->11
200 #now that we've parsed it, deal with the case where everything was 0
201 return $self->Unix(0) if $mon < 0 || $mon > 11;
203 my $tz = lc $args{'Format'} eq 'datemanip'? 'user': 'utc';
204 $self->Unix( $self->Timelocal( $tz, $sec, $min, $hours, $mday, $mon, $year ) );
206 $self->Unix(0) unless $self->Unix > 0;
209 $RT::Logger->warning(
210 "Couldn't parse date '$args{'Value'}' as a $args{'Format'} format"
212 return $self->Unix(0);
215 elsif ( $format eq 'unknown' ) {
216 require Time::ParseDate;
217 # the module supports only legacy timezones like PDT or EST...
218 # so we parse date as GMT and later apply offset, this only
219 # should be applied to absolute times, so compensate shift in NOW
221 $now += ($self->Localtime( $args{Timezone}, $now ))[9];
222 my ($date, $error) = Time::ParseDate::parsedate(
226 UK => RT->Config->Get('DateDayBeforeMonth'),
227 PREFER_PAST => RT->Config->Get('AmbiguousDayInPast'),
228 PREFER_FUTURE => RT->Config->Get('AmbiguousDayInFuture'),
230 unless ( defined $date ) {
231 $RT::Logger->warning(
232 "Couldn't parse date '$args{'Value'}' by Time::ParseDate"
234 return $self->Unix(0);
237 # apply timezone offset
238 $date -= ($self->Localtime( $args{Timezone}, $date ))[9];
241 "RT::Date used Time::ParseDate to make '$args{'Value'}' $date\n"
244 return $self->Unix($date || 0);
248 "Unknown Date format: $args{'Format'}\n"
250 return $self->Unix(0);
258 Set the object's time to the current time. Takes no arguments
259 and returns unix time.
264 return $_[0]->Unix(time);
267 =head2 SetToMidnight [Timezone => 'utc']
269 Sets the date to midnight (at the beginning of the day).
270 Returns the unixtime at midnight.
278 Timezone context C<user>, C<server> or C<UTC>. See also L</Timezone>.
286 my %args = ( Timezone => '', @_ );
287 my $new = $self->Timelocal(
289 0,0,0,($self->Localtime( $args{'Timezone'} ))[3..9]
291 return $self->Unix( $new );
296 Takes either an C<RT::Date> object or the date in unixtime format as a string,
297 if nothing is specified uses the current time.
299 Returns the differnce between the time in the current object and that time
300 as a number of seconds. Returns C<undef> if any of two compared values is
301 incorrect or not set.
308 $other = time unless defined $other;
309 if ( UNIVERSAL::isa( $other, 'RT::Date' ) ) {
310 $other = $other->Unix;
312 return undef unless $other=~ /^\d+$/ && $other > 0;
314 my $unix = $self->Unix;
315 return undef unless $unix > 0;
317 return $unix - $other;
322 Takes either an C<RT::Date> object or the date in unixtime format as a string,
323 if nothing is specified uses the current time.
325 Returns the differnce between C<$self> and that time as a number of seconds as
326 a localized string fit for human consumption. Returns empty string if any of
327 two compared values is incorrect or not set.
333 my $diff = $self->Diff( @_ );
334 return '' unless defined $diff;
336 return $self->DurationAsString( $diff );
339 =head2 DurationAsString
341 Takes a number of seconds. Returns a localized string describing
344 Takes optional named arguments:
350 How many elements to show, how precise it should be. Default is 1,
355 Turn on short notation with one character units, for example
369 # loc("[quant,_1,second]")
370 # loc("[quant,_1,minute]")
371 # loc("[quant,_1,hour]")
372 # loc("[quant,_1,day]")
373 # loc("[quant,_1,week]")
374 # loc("[quant,_1,month]")
375 # loc("[quant,_1,year]")
377 sub DurationAsString {
379 my $duration = int shift;
380 my %args = ( Show => 1, Short => 0, @_ );
382 unless ( $duration ) {
383 return $args{Short}? $self->loc("0s") : $self->loc("0 seconds");
387 $negative = 1 if $duration < 0;
388 $duration = abs $duration;
413 while ( $duration > 0 && ++$i <= $args{'Show'} ) {
416 if ( $duration < $MINUTE ) {
419 elsif ( $duration < ( $coef * $HOUR ) ) {
422 elsif ( $duration < ( $coef * $DAY ) ) {
425 elsif ( $duration < ( $coef * $WEEK ) ) {
428 elsif ( $duration < ( $coef * $MONTH ) ) {
431 elsif ( $duration < $YEAR ) {
437 my $value = int( $duration / $units{$unit} + ($i < $args{'Show'}? 0 : 0.5) );
438 $duration -= int( $value * $units{$unit} );
440 if ( $args{'Short'} ) {
441 push @res, $self->loc("[_1]$unit", $value);
443 push @res, $self->loc("[quant,_1,$long_units{$unit}]", $value);
450 return $self->loc( "[_1] ago", join ' ', @res );
453 return join ' ', @res;
459 Takes nothing. Returns a string that's the differnce between the
460 time in the object and now.
464 sub AgeAsString { return $_[0]->DiffAsString }
470 Returns the object's time as a localized string with curent user's prefered
473 If the current user didn't choose prefered format then system wide setting is
474 used or L</DefaultFormat> if the latter is not specified. See config option
483 return $self->loc("Not set") unless $self->Unix > 0;
485 my $format = RT->Config->Get( 'DateTimeFormat', $self->CurrentUser ) || 'DefaultFormat';
486 $format = { Format => $format } unless ref $format;
487 %args = (%$format, %args);
489 return $self->Get( Timezone => 'user', %args );
492 =head2 GetWeekday DAY
494 Takes an integer day of week and returns a localized string for
495 that day of week. Valid values are from range 0-6, Note that B<0
504 return $self->loc($DAYS_OF_WEEK[$dow])
505 if $DAYS_OF_WEEK[$dow];
509 =head2 GetMonth MONTH
511 Takes an integer month and returns a localized string for that month.
512 Valid values are from from range 0-11.
520 return $self->loc($MONTHS[$mon])
525 =head2 AddSeconds SECONDS
527 Takes a number of seconds and returns the new unix time.
529 Negative value can be used to substract seconds.
535 my $delta = shift or return $self->Unix;
537 $self->Set(Format => 'unix', Value => ($self->Unix + $delta));
539 return ($self->Unix);
542 =head2 AddDays [DAYS]
544 Adds C<24 hours * DAYS> to the current time. Adds one day when
545 no argument is specified. Negative value can be used to substract
548 Returns new unix time.
554 my $days = shift || 1;
555 return $self->AddSeconds( $days * $DAY );
560 Adds 24 hours to the current time. Returns new unix time.
564 sub AddDay { return $_[0]->AddSeconds($DAY) }
566 =head2 Unix [unixtime]
568 Optionally takes a date in unix seconds since the epoch format.
569 Returns the number of seconds since the epoch
575 $self->{'time'} = int(shift || 0) if @_;
576 return $self->{'time'};
581 Alias for L</Get> method. Arguments C<Date> and <Time>
582 are fixed to true values, other arguments could be used
583 as described in L</Get>.
589 unless (defined $self) {
590 use Carp; Carp::confess("undefined $self");
592 return $self->Get( @_, Date => 1, Time => 1 );
597 Takes Format argument which allows you choose date formatter.
598 Pass throught other arguments to the formatter method.
600 Returns the object's formatted date. Default formatter is ISO.
606 return $self->Get( @_, Date => 1, Time => 0 );
616 return $self->Get( @_, Date => 0, Time => 1 );
621 Returnsa a formatted and localized string that represets time of
630 my %args = (Format => 'ISO', @_);
631 my $formatter = $args{'Format'};
632 unless ( $self->ValidFormatter($formatter) ) {
633 RT->Logger->warning("Invalid date formatter '$formatter', falling back to ISO");
636 $formatter = 'ISO' unless $self->can($formatter);
637 return $self->$formatter( %args );
640 =head2 Output formatters
642 Fomatter is a method that returns date and time in different configurable
645 Each method takes several arguments:
653 =item Timezone - Timezone context C<server>, C<user> or C<UTC>
657 Formatters may also add own arguments to the list, for example
658 in RFC2822 format day of time in output is optional so it
659 understand boolean argument C<DayOfTime>.
663 Returns an array of available formatters.
674 =head3 ValidFormatter FORMAT
676 Returns a true value if C<FORMAT> is a known formatter. Otherwise returns
684 return (grep { $_ eq $format } $self->Formatters and $self->can($format))
695 my %args = ( Date => 1,
702 # 0 1 2 3 4 5 6 7 8 9
703 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
704 $self->Localtime($args{'Timezone'});
705 $wday = $self->GetWeekday($wday);
706 $mon = $self->GetMonth($mon);
707 $_ = sprintf "%02d", $_ foreach $mday, $hour, $min, $sec;
709 if( $args{'Date'} && !$args{'Time'} ) {
710 return $self->loc('[_1] [_2] [_3] [_4]',
711 $wday,$mon,$mday,$year);
712 } elsif( !$args{'Date'} && $args{'Time'} ) {
713 if( $args{'Seconds'} ) {
714 return $self->loc('[_1]:[_2]:[_3]',
717 return $self->loc('[_1]:[_2]',
721 if( $args{'Seconds'} ) {
722 return $self->loc('[_1] [_2] [_3] [_4]:[_5]:[_6] [_7]',
723 $wday,$mon,$mday,$hour,$min,$sec,$year);
725 return $self->loc('[_1] [_2] [_3] [_4]:[_5] [_6]',
726 $wday,$mon,$mday,$hour,$min,$year);
733 Returns the L<DateTime::Locale> object representing the current user's locale.
740 my $lang = $self->CurrentUser->UserObj->Lang;
742 require I18N::LangTags::Detect;
743 $lang = ( I18N::LangTags::Detect::detect(), 'en' )[0];
746 return DateTime::Locale->load($lang);
749 =head3 LocalizedDateTime
751 Returns date and time as string, with user localization.
753 Supports arguments: C<DateFormat> and C<TimeFormat> which may contains date and
754 time format as specified in L<DateTime::Locale> (default to C<date_format_full> and
755 C<time_format_medium>), C<AbbrDay> and C<AbbrMonth> which may be set to 0 if
756 you want full Day/Month names instead of abbreviated ones.
760 sub LocalizedDateTime
763 my %args = ( Date => 1,
773 # Require valid names for the format methods
774 my $date_format = $args{DateFormat} =~ /^\w+$/
775 ? $args{DateFormat} : 'date_format_full';
777 my $time_format = $args{TimeFormat} =~ /^\w+$/
778 ? $args{TimeFormat} : 'time_format_medium';
780 my $formatter = $self->LocaleObj;
781 $date_format = $formatter->$date_format;
782 $time_format = $formatter->$time_format;
783 $date_format =~ s/EEEE/EEE/g if ( $args{'AbbrDay'} );
784 $date_format =~ s/MMMM/MMM/g if ( $args{'AbbrMonth'} );
786 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
787 $self->Localtime($args{'Timezone'});
789 my $tz = $self->Timezone($args{'Timezone'});
791 # FIXME : another way to call this module without conflict with local
793 my $dt = DateTime::->new( locale => $formatter,
804 if ( $args{'Date'} && !$args{'Time'} ) {
805 return $dt->format_cldr($date_format);
806 } elsif ( !$args{'Date'} && $args{'Time'} ) {
807 return $dt->format_cldr($time_format);
809 return $dt->format_cldr($date_format) . " " . $dt->format_cldr($time_format);
815 Returns the object's date in ISO format C<YYYY-MM-DD mm:hh:ss>.
816 ISO format is locale independant, but adding timezone offset info
817 is not implemented yet.
819 Supports arguments: C<Timezone>, C<Date>, C<Time> and C<Seconds>.
820 See </Output formatters> for description of arguments.
826 my %args = ( Date => 1,
832 # 0 1 2 3 4 5 6 7 8 9
833 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
834 $self->Localtime($args{'Timezone'});
836 #the month needs incrementing, as gmtime returns 0-11
840 $res .= sprintf("%04d-%02d-%02d", $year, $mon, $mday) if $args{'Date'};
841 $res .= sprintf(' %02d:%02d', $hour, $min) if $args{'Time'};
842 $res .= sprintf(':%02d', $sec, $min) if $args{'Time'} && $args{'Seconds'};
850 Returns the object's date and time in W3C date time format
851 (L<http://www.w3.org/TR/NOTE-datetime>).
853 Format is locale independand and is close enought to ISO, but
854 note that date part is B<not optional> and output string
855 has timezone offset mark in C<[+-]hh:mm> format.
857 Supports arguments: C<Timezone>, C<Time> and C<Seconds>.
858 See </Output formatters> for description of arguments.
871 # 0 1 2 3 4 5 6 7 8 9
872 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
873 $self->Localtime( $args{'Timezone'} );
875 #the month needs incrementing, as gmtime returns 0-11
879 $res .= sprintf("%04d-%02d-%02d", $year, $mon, $mday);
880 if ( $args{'Time'} ) {
881 $res .= sprintf('T%02d:%02d', $hour, $min);
882 $res .= sprintf(':%02d', $sec, $min) if $args{'Seconds'};
884 $res .= sprintf "%s%02d:%02d", $self->_SplitOffset( $offset );
894 =head3 RFC2822 (MIME)
896 Returns the object's date and time in RFC2822 format,
897 for example C<Sun, 06 Nov 1994 08:49:37 +0000>.
898 Format is locale independand as required by RFC. Time
899 part always has timezone offset in digits with sign prefix.
901 Supports arguments: C<Timezone>, C<Date>, C<Time>, C<DayOfWeek>
902 and C<Seconds>. See </Output formatters> for description of
909 my %args = ( Date => 1,
917 # 0 1 2 3 4 5 6 7 8 9
918 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
919 $self->Localtime($args{'Timezone'});
921 my ($date, $time) = ('','');
922 $date .= "$DAYS_OF_WEEK[$wday], " if $args{'DayOfWeek'} && $args{'Date'};
923 $date .= "$mday $MONTHS[$mon] $year" if $args{'Date'};
925 if ( $args{'Time'} ) {
926 $time .= sprintf("%02d:%02d", $hour, $min);
927 $time .= sprintf(":%02d", $sec) if $args{'Seconds'};
928 $time .= sprintf " %s%02d%02d", $self->_SplitOffset( $offset );
931 return join ' ', grep $_, ($date, $time);
934 =head3 RFC2616 (HTTP)
936 Returns the object's date and time in RFC2616 (HTTP/1.1) format,
937 for example C<Sun, 06 Nov 1994 08:49:37 GMT>. While the RFC describes
938 version 1.1 of HTTP, but the same form date can be used in version 1.0.
940 Format is fixed length, locale independand and always represented in GMT
941 what makes it quite useless for users, but any date in HTTP transfers
942 must be presented using this format.
944 HTTP-date = rfc1123 | ...
945 rfc1123 = wkday "," SP date SP time SP "GMT"
946 date = 2DIGIT SP month SP 4DIGIT
947 ; day month year (e.g., 02 Jun 1982)
948 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
949 ; 00:00:00 - 23:59:59
950 wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"
951 month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun"
952 | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
954 Supports arguments: C<Date> and C<Time>, but you should use them only for
955 some personal reasons, RFC2616 doesn't define any optional parts.
956 See </Output formatters> for description of arguments.
962 my %args = ( Date => 1, Time => 1,
965 Seconds => 1, DayOfWeek => 1,
968 my $res = $self->RFC2822( %args );
969 $res =~ s/\s*[+-]\d\d\d\d$/ GMT/ if $args{'Time'};
975 Returns the object's date and time in iCalendar format.
976 If only date requested then users timezone is used, otherwise
979 Supports arguments: C<Date> and C<Time>.
980 See </Output formatters> for description of arguments.
987 Date => 1, Time => 1,
992 if ( $args{'Date'} && !$args{'Time'} ) {
998 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$ydaym,$isdst,$offset) =
999 $self->Localtime( $tz );
1001 #the month needs incrementing, as gmtime returns 0-11
1005 if ( $args{'Date'} && !$args{'Time'} ) {
1006 $res = sprintf( '%04d%02d%02d', $year, $mon, $mday );
1008 elsif ( !$args{'Date'} && $args{'Time'} ) {
1009 $res = sprintf( 'T%02d%02d%02dZ', $hour, $min, $sec );
1012 $res = sprintf( '%04d%02d%02dT%02d%02d%02dZ', $year, $mon, $mday, $hour, $min, $sec );
1017 # it's been added by mistake in 3.8.0
1018 sub iCalDate { return (shift)->iCal( Time => 0, @_ ) }
1021 my ($self, $offset) = @_;
1022 my $sign = $offset < 0? '-': '+';
1023 $offset = int( (abs $offset) / 60 + 0.001 );
1024 my $mins = $offset % 60;
1025 my $hours = int( $offset/60 + 0.001 );
1026 return $sign, $hours, $mins;
1029 =head2 Timezones handling
1031 =head3 Localtime $context [$time]
1033 Takes one mandatory argument C<$context>, which determines whether
1034 we want "user local", "system" or "UTC" time. Also, takes optional
1035 argument unix C<$time>, default value is the current unix time.
1037 Returns object's date and time in the format provided by perl's
1038 builtin functions C<localtime> and C<gmtime> with two exceptions:
1040 1) "Year" is a four-digit year, rather than "years since 1900"
1042 2) The last element of the array returned is C<offset>, which
1043 represents timezone offset against C<UTC> in seconds.
1050 my $tz = $self->Timezone(shift);
1052 my $unix = shift || $self->Unix;
1053 $unix = 0 unless $unix >= 0;
1057 @local = gmtime($unix);
1060 local $ENV{'TZ'} = $tz;
1061 ## Using POSIX::tzset fixes a bug where the TZ environment variable
1064 @local = localtime($unix);
1066 POSIX::tzset(); # return back previouse value
1068 $local[5] += 1900; # change year to 4+ digits format
1069 my $offset = Time::Local::timegm_nocheck(@local) - $unix;
1070 return @local, $offset;
1073 =head3 Timelocal $context @time
1075 Takes argument C<$context>, which determines whether we should
1076 treat C<@time> as "user local", "system" or "UTC" time.
1078 C<@time> is array returned by L<Localtime> functions. Only first
1079 six elements are mandatory - $sec, $min, $hour, $mday, $mon and $year.
1080 You may pass $wday, $yday and $isdst, these are ignored.
1082 If you pass C<$offset> as ninth argument, it's used instead of
1083 C<$context>. It's done such way as code
1084 C<$self->Timelocal('utc', $self->Localtime('server'))> doesn't
1085 makes much sense and most probably would produce unexpected
1086 result, so the method ignore 'utc' context and uses offset
1087 returned by L<Localtime> method.
1094 if ( defined $_[9] ) {
1095 return timegm(@_[0..5]) - $_[9];
1097 $tz = $self->Timezone( $tz );
1098 if ( $tz eq 'UTC' ) {
1099 return Time::Local::timegm(@_[0..5]);
1103 local $ENV{'TZ'} = $tz;
1104 ## Using POSIX::tzset fixes a bug where the TZ environment variable
1107 $rv = Time::Local::timelocal(@_[0..5]);
1109 POSIX::tzset(); # switch back to previouse value
1116 =head3 Timezone $context
1118 Returns the timezone name.
1120 Takes one argument, C<$context> argument which could be C<user>, C<server> or C<utc>.
1126 Default value is C<user> that mean it returns current user's Timezone value.
1130 If context is C<server> it returns value of the C<Timezone> RT config option.
1134 If both server's and user's timezone names are undefined returns 'UTC'.
1144 Carp::carp "RT::Date->Timezone is a setter only";
1148 my $context = lc(shift);
1151 if( $context eq 'user' ) {
1152 $tz = $self->CurrentUser->UserObj->Timezone;
1153 } elsif( $context eq 'server') {
1154 $tz = RT->Config->Get('Timezone');
1158 $tz ||= RT->Config->Get('Timezone') || 'UTC';
1159 $tz = 'UTC' if lc $tz eq 'gmt';
1164 RT::Base->_ImportOverlays();