############################################################################### # DateTime.pm # # $Date: 01.05.16 $ # ############################################################################### # YaBB: Yet another Bulletin Board # # Open-Source Community Software for Webmasters # # Version: YaBB 2.6.12 # # Packaged: January 5, 2016 # # Distributed by: http://www.yabbforumsoftware.com # # =========================================================================== # # Copyright (c) 2000-2016 YaBB (www.yabbforumsoftware.com) - All Rights Reserved. # # Software by: The YaBB Development Team # # with assistance from the YaBB community. # ############################################################################### no warnings qw(uninitialized once redefine); use CGI::Carp qw(fatalsToBrowser); use English qw(-no_match_vars); use Time::Local; our $VERSION = '2.6.12'; $datetimepmver = 'YaBB 2.6.12 $Revision: 1651 $'; @days_rfc = qw( Sun Mon Tue Wed Thu Fri Sat ); # for RFC compliant feed time @months_rfc = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); sub calcdifference { # Input: $date1 $date2 $result = int( $date2 / 86400 ) - int( $date1 / 86400 ); return $result; } sub toffs { my ($mydate, $forum_default) = @_; my $toffs = 0; if ( $iamguest || $forum_default || !${ $uid . $username }{'user_tz'} ) { $tzname = $default_tz || 'UTC'; } else { $tzname = ${ $uid . $username }{'user_tz'}; } eval { require DateTime; require DateTime::TimeZone; }; if( !$EVAL_ERROR ) { DateTime->import(); DateTime::TimeZone->import(); if ( $tzname eq 'local' ) { $tzname = 'UTC'; } my $tz = DateTime::TimeZone->new(name => $tzname); my $now = DateTime->from_epoch( 'epoch' => $mydate ); $toffs = $tz->offset_for_datetime($now); } elsif ( $EVAL_ERROR ) { if ( $tzname eq 'local' ) { $toffs = $timeoffset; $toffs += ( localtime( $mydate + ( 3600 * $toffs ) ) )[8] ? $dstoffset : 0; $toffs = 3600 * $toffs; } else { $toffs = 0; } } else { $toffs = 0; } return $toffs; } sub timetostring { my ($thedate) = @_; return 0 if !$thedate; if ( !$maintxt{'107'} ) { $maintxt{'107'} = 'at'; } my $toffs = 0; if ($enabletz) { $toffs = toffs($thedate); } my $newtime = $thedate + $toffs; ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, undef ) = gmtime( $newtime ); $sec = sprintf '%02d', $sec; $min = sprintf '%02d', $min; $hour = sprintf '%02d', $hour; $mday = sprintf '%02d', $mday; $mon_num = $mon + 1; $mon_num = sprintf '%02d', $mon_num; $year = 1900 + $year; $saveyear = ( $year % 100 ); $saveyear = sprintf '%02d', $saveyear; return "$mon_num/$mday/$saveyear $maintxt{'107'} $hour\:$min\:$sec"; } # generic string-to-time converter sub stringtotime { my ($spvar) = @_; if ( !$spvar ) { return 0; } $splitvar = $spvar; # receive standard format yabb date/time string. # allow for oddities thrown up from y1 , with full year / single digit day/month my $amonth = 1; my $aday = 1; my $ayear = 0; my $ahour = 0; my $amin = 0; my $asec = 0; if ( $splitvar =~ m/(\d{1,2})\/(\d{1,2})\/(\d{2,4}).*?(\d{1,2})\:(\d{1,2})\:(\d{1,2})/sm ) { $amonth = int $1; $aday = int $2; $ayear = int $3; $ahour = int $4; $amin = int $5; $asec = int $6; } elsif ( $splitvar =~ m/(\d{1,2})\/(\d{1,2})\/(\d{2,4})/sm ) { $amonth = int $1; $aday = int $2; $ayear = int $3; $ahour = 0; $amin = 0; $asec = 0; } # Uses 1904 and 2036 as the default dates, as both are leap years. # If we used the real extremes (1901 and 2038) - there would be problems # As time dies if you provide 29th Feb as a date in a non-leap year # Using leap years as the default years prevents this from happening. if ( $ayear >= 36 && $ayear <= 99 ) { $ayear += 1900; } elsif ( $ayear >= 00 && $ayear <= 35 ) { $ayear += 2000; } if ( $ayear < 1904 ) { $ayear = 1904; } elsif ( $ayear > 2036 ) { $ayear = 2036; } if ( $amonth < 1 ) { $amonth = 0; } elsif ( $amonth > 12 ) { $amonth = 11; } else { --$amonth; } if ( $amonth == 3 || $amonth == 5 || $amonth == 8 || $amonth == 10 ) { $max_days = 30; } elsif ( $amonth == 1 && $ayear % 4 == 0 ) { $max_days = 29; } elsif ( $amonth == 1 && $ayear % 4 != 0 ) { $max_days = 28; } else { $max_days = 31; } if ( $aday > $max_days ) { $aday = $max_days; } if ( $ahour < 1 ) { $ahour = 0; } elsif ( $ahour > 23 ) { $ahour = 23; } if ( $amin < 1 ) { $amin = 0; } elsif ( $amin > 59 ) { $amin = 59; } if ( $asec < 1 ) { $asec = 0; } elsif ( $asec > 59 ) { $asec = 59; } return ( timegm( $asec, $amin, $ahour, $aday, $amonth, $ayear ) ); } sub timeformat { my ( $oldformat, $dontusetoday, $use_rfc, $forum_default, $lower ) = @_; # use forum default time and format $mytimeselected = ( $forum_default || !${ $uid . $username }{'timeselect'} ) ? $timeselected : ${ $uid . $username }{'timeselect'}; chomp $oldformat; return if !$oldformat; # find out what timezone is to be used. my $toffs = 0; if ( $enabletz) { $toffs = toffs($oldformat, $forum_default); } my $mynewtime = $oldformat + $toffs; my ( $newsecond, $newminute, $newhour, $newday, $newmonth, $newyear, $newweekday, $newyearday, $newoff ) = gmtime( $mynewtime ); $newmonth++; $newyear += 1900; # Calculate number of full weeks this year $newweek = int( ( $newyearday + 1 - $newweekday ) / 7 ) + 1; # Add 1 if today isn't Saturday if ( $newweekday < 6 ) { $newweek = $newweek + 1; } $newweek = sprintf '%02d', $newweek; if ($use_rfc) { $shortday = $days_rfc[$newweekday]; } else { $shortday = $days_short[$newweekday]; } $longday = $days[$newweekday]; $newmonth = sprintf '%02d', $newmonth; $newshortyear = ( $newyear % 100 ); $newshortyear = sprintf '%02d', $newshortyear; if ( $mytimeselected != 4 && $mytimeselected != 8 ) { $newday = sprintf '%02d', $newday; } $newhour = sprintf '%02d', $newhour; $newminute = sprintf '%02d', $newminute; $newsecond = sprintf '%02d', $newsecond; $newtime = $newhour . q{:} . $newminute . q{:} . $newsecond; ( undef, undef, undef, undef, undef, $yy, undef, $yd, undef ) = gmtime( $date + $toffs ); $yy += 1900; $daytxt = undef; # must be a global variable if ( !$dontusetoday ) { if ( $yd == $newyearday && $yy == $newyear ) { # today $daytxt = qq~$maintxt{'769'}~; if ( $lower && $maintxt{'769l'} ) { $daytxt = qq~$maintxt{'769l'}~; } } elsif ( ( ( $yd - 1 ) == $newyearday && $yy == $newyear ) || ( $yd == 0 && $newday == 31 && $newmonth == 12 && ( $yy - 1 ) == $newyear ) ) { # yesterday || yesterday, over a year end. $daytxt = qq~$maintxt{'769a'}~; if ( $lower && $maintxt{'769al'} ) { $daytxt = qq~$maintxt{'769al'}~; } } } if ( !$maintxt{'107'} ) { $maintxt{'107'} = $admin_txt{'107'}; } my @timform = ( q{}, time_1( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_2( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_3( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_4( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute, $lower ), time_5( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), time_6( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), q{}, time_8( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), ); foreach my $i ( 1 .. 8 ) { if ( $mytimeselected == $i ) { $newformat = $timform[$i]; } } return $newformat; } sub timeformatcal { my ( $mynewtime, $usetoday ) = @_; # use forum default time and format $mytimeselected = ( $forum_default || !${ $uid . $username }{'timeselect'} ) ? $timeselected : ${ $uid . $username }{'timeselect'}; chomp $mynewtime; return if !$mynewtime; # find out what timezone is to be used. my $toffs = 0; my ( $newsecond, $newminute, $newhour, $newday, $newmonth, $newyear, $newweekday, $newyearday, $newoff ) = gmtime( $mynewtime ); $newmonth++; $newyear += 1900; # Calculate number of full weeks this year $newweek = int( ( $newyearday + 1 - $newweekday ) / 7 ) + 1; # Add 1 if today isn't Saturday if ( $newweekday < 6 ) { $newweek = $newweek + 1; } $newweek = sprintf '%02d', $newweek; if ($use_rfc) { $shortday = $days_rfc[$newweekday]; } else { $shortday = $days_short[$newweekday]; } $longday = $days[$newweekday]; $newmonth = sprintf '%02d', $newmonth; $newshortyear = ( $newyear % 100 ); $newshortyear = sprintf '%02d', $newshortyear; if ( $mytimeselected != 4 && $mytimeselected != 8 ) { $newday = sprintf '%02d', $newday; } $newhour = sprintf '%02d', $newhour; $newminute = sprintf '%02d', $newminute; $newsecond = sprintf '%02d', $newsecond; $newtime = $newhour . q{:} . $newminute . q{:} . $newsecond; if ( $enabletz) { $toffs = toffs($date); } ( undef, undef, undef, undef, undef, $yy, undef, $yd, undef ) = gmtime( $date + $toffs ); $yy += 1900; $daytxt = undef; # must be a global variable if ( $usetoday == 1 ) { $myleap = IsLeap($yy); if ( $yd == $newyearday && $yy == $newyear ) { # today $daytxt = qq~$maintxt{'769'}~; } elsif ( ( ( $yd - 1 ) == $newyearday && $yy == $newyear ) || ( $yd == 0 && $newday == 31 && $newmonth == 12 && ( $yy - 1 ) == $newyear ) ) { # yesterday || yesterday, over a year end. $daytxt = qq~$maintxt{'769a'}~; } elsif ( ( ( $yd + 1 ) == $newyearday && $yy == $newyear ) || ( $yd == ( 365 + $myleap ) && $newday == 1 && $newmonth == 0 && ( $yy + 1 ) == $newyear ) ) { # tomorrow || tomorrow, over a year end. $daytxt = qq~$maintxt{'769b'}~; } } if ( !$maintxt{'107'} ) { $maintxt{'107'} = $admin_txt{'107'}; } my @timform = ( q{}, time_1( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_2( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_3( $daytxt, $newday, $newmonth, $newyear, $newtime ), time_4( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), time_5( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), time_6( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), q{}, time_8( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ), ); foreach my $i ( 1 .. 8 ) { if ( $mytimeselected == $i ) { $newformat = $timform[$i]; } } $newformat = dtonly($newformat); return $newformat; } sub CalcAge { my ( $user, $act ) = @_; timetostring($date); my ( $usermonth, $userday, $useryear ); if ( ${ $uid . $user }{'bday'} ne q{} ) { ( $usermonth, $userday, $useryear ) = split /\//xsm, ${ $uid . $user }{'bday'}; if ( $act eq 'calc' ) { if ( length( ${ $uid . $user }{'bday'} ) <= 2 ) { $age = ${ $uid . $user }{'bday'}; } else { $age = $year - $useryear; if ( $usermonth > $mon_num || ( $usermonth == $mon_num && $userday > $mday ) ) { --$age; } } } if ( $act eq 'parse' ) { if ( length( ${ $uid . $user }{'bday'} ) <= 2 ) { return; } $umonth = $usermonth; $uday = $userday; $uyear = $useryear; } if ( $act eq 'isbday' ) { if ( $usermonth == $mon_num && $userday == $mday ) { $isbday = 'yes'; } } } else { $age = q{}; $isbday = q{}; } return; } sub NumberFormat { my ($inp) = @_; my ( $decimal, $fraction ) = split /\./xsm, $inp; my $tmpforumformat = $forumnumberformat || 1; my $numberformat = ${ $uid . $username }{'numberformat'} || $tmpforumformat; my @septor = ( [ q{}, q{}, q{,}, q{.}, q{ }, ], [ q{.}, q{,}, q{.}, q{,}, q{,}, ], ); foreach my $i ( 0 .. 4 ) { $dra = $septor[0]->[$i]; $drb = $septor[1]->[$i]; if ( $numberformat == ( $i + 1 ) ) { $separator = $dra; $decimalpt = $drb; } } if ( $decimal =~ m/\d{4,}/sm ) { $decimal = reverse $decimal; $decimal =~ s/(\d{3})/$1$separator/gsm; $decimal = reverse $decimal; $decimal =~ s/^(\.|\,| )//sm; } $newnumber = $decimal; if ($fraction) { $newnumber .= "$decimalpt$fraction"; } return $newnumber; } sub time_1 { my ( $daytxt, $newday, $newmonth, $newyear, $newtime ) = @_; $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newtime~ : qq~$newmonth/$newday/$newshortyear $maintxt{'107'} $newtime~; return $newformat; } sub time_2 { my ( $daytxt, $newday, $newmonth, $newyear, $newtime ) = @_; $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newtime~ : qq~$newday.$newmonth.$newshortyear $maintxt{'107'} $newtime~; return $newformat; } sub time_3 { my ( $daytxt, $newday, $newmonth, $newyear, $newtime ) = @_; $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newtime~ : qq~$newday.$newmonth.$newyear $maintxt{'107'} $newtime~; return $newformat; } sub time_4 { my ( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute, $lower ) = @_; $ampm = $newhour > 11 ? 'pm' : 'am'; $newhour2 = $newhour % 12 || 12; if ( !@months_m ) { @months_m = @months; } if ($use_rfc) { $newmonth2 = $months_rfc[ $newmonth - 1 ]; } elsif ( $lower ) { $newmonth2 = $months_m[ $newmonth - 1 ]; } else { $newmonth2 = $months[ $newmonth - 1 ]; } $newday2 = "$timetxt{'4'}"; if ( $newday > 10 && $newday < 20 ) { $newday2 = "$timetxt{'4'}"; } else { foreach my $i ( 1 .. 3 ) { if ( $newday % 10 == $i ) { $newday2 = qq~$timetxt{$i}~; } } } $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newhour2:$newminute$ampm~ : qq~$newmonth2$maintxt{'770'} $newday$newday2, $newyear $maintxt{'107'} $newhour2:$newminute$ampm~; return $newformat; } sub time_5 { my ( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ) = @_; $ampm = $newhour > 11 ? 'pm' : 'am'; $newhour2 = $newhour % 12 || 12; $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newhour2:$newminute$ampm~ : qq~$newmonth/$newday/$newshortyear $maintxt{'107'} $newhour2:$newminute$ampm~; return ($newformat); } sub time_6 { my ( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ) = @_; if ($use_rfc) { $newmonth2 = $months_rfc[ $newmonth - 1 ]; } elsif ( @months_m ) { $newmonth2 = $months_m[ $newmonth - 1 ]; } else { $newmonth2 = $months[ $newmonth - 1 ]; } $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newhour:$newminute~ : qq~$newday. $newmonth2$maintxt{'770a'} $newyear $maintxt{'107'} $newhour:$newminute~; return $newformat; } sub time_8 { my ( $daytxt, $newday, $newmonth, $newyear, $newhour, $newminute ) = @_; $ampm = $newhour > 11 ? 'pm' : 'am'; $newhour2 = $newhour % 12 || 12; if ($use_rfc) { $newmonth2 = $months_rfc[ $newmonth - 1 ]; } elsif ( @months_m ) { $newmonth2 = $months_m[ $newmonth - 1 ]; } else { $newmonth2 = $months[ $newmonth - 1 ]; } $newday2 = "$timetxt{'4'}"; if ( $newday > 10 && $newday < 20 ) { $newday2 = "$timetxt{'4'}"; } else { foreach my $i ( 1 .. 3 ) { if ( $newday % 10 == $i ) { $newday2 = qq~$timetxt{$i}~; } } } $newformat = $daytxt ? qq~$daytxt $maintxt{'107'} $newhour2:$newminute$ampm~ : qq~$newday$newday2 $newmonth2$maintxt{'770a'}, $newyear $maintxt{'107'} $newhour2:$newminute$ampm~; return $newformat; } sub dtonly { my ($newformat) = @_; if ( $newformat =~ m/\A(.*?)\s*$maintxt{'107'}\s*(.*?)\Z/ism ) { $dateonly = $1; } return ($dateonly); } sub tmonly { my ($newformat) = @_; if ( $newformat =~ m/\A(.*?)\s*$maintxt{'107'}\s*(.*?)\Z/ism ) { $timeonly = $2; } return ($timeonly); } sub bdayno_year { my ($newformat) = @_; $date_noyear = $newformat; if ( $mytimeselected == 4 || $mytimeselected == 8 ) { ( $date_noyear, undef ) = split /\,/xsm, $newformat; } elsif ( $mytimeselected == 1 || $mytimeselected == 5 ) { @date_noyear = split /\//xsm, $newformat; $date_noyear = qq~$date_noyear[0]~ . q{/} . qq~$date_noyear[1]~; } elsif ( $mytimeselected == 2 || $mytimeselected == 3 ) { @date_noyear = split /[.]/xsm, $newformat; $date_noyear = qq~$date_noyear[0]~ . q{/} . qq~$date_noyear[1]~; } elsif ( $mytimeselected == 6 ) { @date_noyear = split / /sm, $newformat; $date_noyear = qq~$date_noyear[0] $date_noyear[1]~; } return ($date_noyear); } sub IsLeap { my ($year ) = @_; return 0 if $year % 4; return 1 if $year % 100; return 0 if $year % 400; return 1; } sub ctbtime { my ( $newsecond, $newminute, $newhour, $newday, $newmonth, $newyear, $newweekday, $newyearday, $newoff ) = gmtime( $date ); $newyear += 1900; $shortday = $days_rfc[$newweekday]; $shortmon = $months_rfc[$newmonth]; $newhour = sprintf '%02d', $newhour; $newminute = sprintf '%02d', $newminute; $newsecond = sprintf '%02d', $newsecond; $newmin = $newhour . q{:} . $newminute . q{:} . $newsecond; $newtime = qq~$shortday, $newday $shortmon $newyear $newmin UTC~; return $newtime; } 1;