[interchange-cvs] interchange - pajamian modified 8 files

interchange-cvs at icdevgroup.org interchange-cvs at icdevgroup.org
Fri May 1 13:50:01 UTC 2009


User:      pajamian
Date:      2009-05-01 13:50:01 GMT
Modified:  code/Filter duration.filter
Modified:  code/UserTag component.tag convert_date.tag css.tag
Modified:  dist/standard/config pay_cert.tag
Modified:  lib/Vend Interpolate.pm UserDB.pm Util.pm
Log:
* New adjust_time() function allows time adjustment based on secs, mins, hours,
  days, weeks, months and years.  Also can string multiple adjustments together
  and compensate for daylight savings time changes over the adjustment period.

  This sub (in Util.pm) accepts up to three arguments.  The first (required)
  argument is the adjustment to be made and is a signed number followed by one
  of seconds, minutes, hours, days, weeks, months or years (these can be
  abbreviated).  The second optional argument is a unixtime to be adjusted and
  defaults to the current time.  If the third argument is true then the
  resulting time will be compensated for any daylight savings time differences.
  The sub uses POSIX::mktime() to do the conversions and so does not come with a
  new module requirement for Interchange.

* _set_acl() in UserDB.pm now uses adjust_time() instead of time_to_seconds().

* [pay-cert] tag now uses the new adjust_time() function instead of the older
  time_to_seconds().

* [component], [convert-date] and [css] now use the new adjust_time() function
  instead of the older time_to_seconds().

* [convert-date] now has new compensate_dst argument that when set to 1 will
   compensate the adjusted time for daylight savings time changes (it basically
   passes 1 as the third argument to adjust_time()).

* fixed bug in [convert-date] that skewed the time by one hour if the starting
  date was during daylight savings time and an adjustment was made.

* [time] now uses adjust_time() instead of the older time_to_seconds().  There
  is also a new compensate_dst attribute that when set to 1 will compensate the
  adjusted time for daylight savings time changes (it basically passes 1 as the
  third argument to adjust_time()).

Following are examples that help to illustrate all of the above new features.
Note that many of the examples may require adjustment depending on your local
time zone and locale settings:

Code:
<pre>
Current time: [time]%c[/time]
+5 hours: [time adjust="+5 hours"]%c[/time]
+5 years: [time adjust="+5 years"]%c[/time]
-8.3 months: [time adjust="-8.3 months"]%c[/time]
+2.6 days: [time adjust="+2.6 days"]%c[/time]
+7.7 months: [time adjust="+7.7 months"]%c[/time]
+7 months: [time adjust="+7 months"]%c[/time]
+7 months (compensate_dst): [time adjust="+7 months" compensate_dst=1]%c[/time]
+5: [time adjust="+5"]%c[/time]
-500 hours=1: [time adjust="-500" hours=1]%c[/time]
hours=+500: [time hours=+500]%c[/time]
+500: [time adjust="+500"]%c[/time]
+5 years, 6 months, 3 days, -4 hours, 7 minutes (compensate_dst): [time adjust="+5 years, 6 months, 3 days, -4 hours, 7 minutes" compensate_dst=1]%c[/time]

duration filter:
[cgi name=start_date set=200502120800 hide=1]
[cgi name=offset set="12 hours 10 mins" hide=1]
20050212201000: [filter duration.start_date.offset][/filter]
20050212200500: [filter duration.-dummy.12.hours.5.mins]200502120800[/filter]

convert-date tag:
200807151600: [convert-date adjust="+6 months" format="%c"]200807151600[/convert-date]
200807151600 (compensate_dst): [convert-date adjust="+6 months" format="%c" compensate_dst=1]200807151600[/convert-date]
</pre>

Results:
Current time: Fri May  1 05:40:47 2009
+5 hours: Fri May  1 10:40:47 2009
+5 years: Thu May  1 05:40:47 2014
-8.3 months: Fri Aug 22 22:28:47 2008
+2.6 days: Sun May  3 20:04:47 2009
+7.7 months: Tue Dec 22 21:28:46 2009
+7 months: Tue Dec  1 04:40:47 2009
+7 months (compensate_dst): Tue Dec  1 05:40:47 2009
+5: Fri May  1 10:40:47 2009
-500 hours=1: Fri Apr 10 09:40:47 2009
hours=+500: Fri May 22 01:40:47 2009
+500: Fri May  1 10:40:47 2009
+5 years, 6 months, 3 days, -4 hours, 7 minutes (compensate_dst): Tue Nov  4 01:33:47 2014

duration filter:

20050212201000: 20050212201000
20050212200500: 20050212200500

convert-date tag:
200807151600 +6 months: Thu 15 Jan 2009 03:00:00 PM PST
(compensate_dst): Thu 15 Jan 2009 04:00:00 PM PST

Revision  Changes    Path
1.7                  interchange/code/Filter/duration.filter


rev 1.7, prev_rev 1.6
Index: duration.filter
===================================================================
RCS file: /var/cvs/interchange/code/Filter/duration.filter,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- duration.filter	30 Mar 2007 23:40:44 -0000	1.6
+++ duration.filter	1 May 2009 13:50:00 -0000	1.7
@@ -6,7 +6,7 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: duration.filter,v 1.6 2007-03-30 23:40:44 pajamian Exp $
+# $Id: duration.filter,v 1.7 2009-05-01 13:50:00 pajamian Exp $
 
 CodeDef duration Filter
 CodeDef duration Description Duration
@@ -30,19 +30,14 @@
 	use vars qw/$CGI/;
 	my $start = $CGI->{$startvar} || $val;
 	my $durstring = $CGI->{$durvar};
-	my $duration = 0;
 	use Time::Local;
 
 	if (!length($durstring) && $durvar =~ /^\d+$/) {
 		$durstring = join(' ', $durvar, @extra);
 	}
 
-	while($durstring =~ s/(\d+\s*[hmwd]\w*)\s*//) {
-		$duration += Vend::Config::time_to_seconds($1);
-	}
-
 	## Want to allow setting the value directly
-	return $val unless $duration;
+	return $val unless $durstring;
 
 	$start =~ s/\0+//g;
 	if($start =~ m:(\d+)[-/]+(\d+)[-/]+(\d+):) {
@@ -73,7 +68,9 @@
 		logError("bad time value passed to duration filter: %s", $@);
 		return 0;
 	}
-	$time += $duration;
+
+	$time = adjust_time($durstring, $time);
+
 	return POSIX::strftime("%Y%m%d%H%M%S", localtime($time));
 }
 EOR



1.10                 interchange/code/UserTag/component.tag


rev 1.10, prev_rev 1.9
Index: component.tag
===================================================================
RCS file: /var/cvs/interchange/code/UserTag/component.tag,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- component.tag	30 Mar 2007 23:40:56 -0000	1.9
+++ component.tag	1 May 2009 13:50:00 -0000	1.10
@@ -5,12 +5,12 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: component.tag,v 1.9 2007-03-30 23:40:56 pajamian Exp $
+# $Id: component.tag,v 1.10 2009-05-01 13:50:00 pajamian Exp $
 
 UserTag component Order     component
 UserTag component addAttr
 UserTag component NoReparse 1
-UserTag component Version   $Revision: 1.9 $
+UserTag component Version   $Revision: 1.10 $
 UserTag component Routine   <<EOR
 sub {
 	my ($name, $opt) = @_;
@@ -105,10 +105,7 @@
 		$crecord = $cdb->row_hash($cache_it) || {};
 		$now = time;
 		
-		my $secs	= $record->{cache_interval} =~ /\D/
-					? time_to_seconds($record->{cache_interval}) 
-					: $record->{cache_interval};
-		my $exp = $crecord->{cache_time} + $secs;
+		my $exp = adjust_time($record->{cache_interval}, $crecord->{cache_time});
 		
 		if ($exp > $now) {
 			# Increment control_index as not done below



1.9                  interchange/code/UserTag/convert_date.tag


rev 1.9, prev_rev 1.8
Index: convert_date.tag
===================================================================
RCS file: /var/cvs/interchange/code/UserTag/convert_date.tag,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- convert_date.tag	29 Jan 2009 10:47:40 -0000	1.8
+++ convert_date.tag	1 May 2009 13:50:00 -0000	1.9
@@ -5,7 +5,7 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: convert_date.tag,v 1.8 2009-01-29 10:47:40 racke Exp $
+# $Id: convert_date.tag,v 1.9 2009-05-01 13:50:00 pajamian Exp $
 
 UserTag convert-date Order       adjust
 UserTag convert-date PosNumber   1
@@ -14,7 +14,7 @@
 UserTag convert-date AttrAlias   days adjust
 UserTag convert-date HasEndTag
 UserTag convert-date Interpolate
-UserTag convert-date Version     $Revision: 1.8 $
+UserTag convert-date Version     $Revision: 1.9 $
 UserTag convert-date Routine     <<EOR
 sub {
     my ($adjust, $opt, $text) = @_;
@@ -32,6 +32,7 @@
 		$t[5] = $1 - 1900;
 		$t[4] = $2 - 1;
 		$t[3] = $3;
+		$t[8] = -1;
 	} 
 	elsif($text =~ /\d/) {
 					$text =~ s/\D//g;
@@ -42,6 +43,7 @@
 					$t[4] = $2 - 1;
 					$t[5] = $1;
 					$t[5] -= 1900;
+					$t[8] = -1;
 	}
 	elsif (exists $opt->{empty}) {
 		return $opt->{empty};
@@ -54,13 +56,7 @@
 	if ($adjust) {
 		$now ||= POSIX::mktime(@t);
 		$adjust .= ' days' if $adjust =~ /^[-\s\d]+$/;
-
-		if ($adjust =~ s/^\s*-\s*//) {
-			@t = localtime($now - Vend::Config::time_to_seconds($adjust));
-		}
-		else {
-			@t = localtime($now + Vend::Config::time_to_seconds($adjust));
-		}
+		@t = localtime(adjust_time($adjust, $now, $opt->{compensate_dst}));
 	}
 
 	if (defined $opt->{raw} and Vend::Util::is_yes($opt->{raw})) {



1.9                  interchange/code/UserTag/css.tag


rev 1.9, prev_rev 1.8
Index: css.tag
===================================================================
RCS file: /var/cvs/interchange/code/UserTag/css.tag,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- css.tag	30 Mar 2007 23:40:56 -0000	1.8
+++ css.tag	1 May 2009 13:50:00 -0000	1.9
@@ -5,11 +5,11 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: css.tag,v 1.8 2007-03-30 23:40:56 pajamian Exp $
+# $Id: css.tag,v 1.9 2009-05-01 13:50:00 pajamian Exp $
 
 UserTag css Order   name
 UserTag css addAttr
-UserTag css Version $Revision: 1.8 $
+UserTag css Version $Revision: 1.9 $
 UserTag css Routine <<EOR
 sub {
 	my ($name, $opt) = @_;
@@ -72,9 +72,7 @@
 		elsif($opt->{timed}) {
 			my $now = time();
 			$opt->{timed} .= ' min' if $opt->{timed} =~ /^\d+$/;
-			my $secs = Vend::Config::time_to_seconds($opt->{timed});
-#::logDebug("timed seconds = $secs");
-			my $fliptime = $stat[9] + $secs;
+			my $fliptime = adjust_time($opt->{timed}, $stat[9]);
 #::logDebug("fliptime=$fliptime now=$now");
 			if ($fliptime <= $now) {
 				$write = 1;



1.4                  interchange/dist/standard/config/pay_cert.tag


rev 1.4, prev_rev 1.3
Index: pay_cert.tag
===================================================================
RCS file: /var/cvs/interchange/dist/standard/config/pay_cert.tag,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- pay_cert.tag	9 Aug 2007 13:40:53 -0000	1.3
+++ pay_cert.tag	1 May 2009 13:50:00 -0000	1.4
@@ -5,7 +5,7 @@
 # the Free Software Foundation; either version 2 of the License, or
 # (at your option) any later version.  See the LICENSE file for details.
 # 
-# $Id: pay_cert.tag,v 1.3 2007-08-09 13:40:53 pajamian Exp $
+# $Id: pay_cert.tag,v 1.4 2009-05-01 13:50:00 pajamian Exp $
 
 UserTag pay-cert Order code
 UserTag pay-cert addAttr
@@ -89,12 +89,11 @@
 			@date_expires = @date_issued;
 			$date_expires[4] += $1;
 		}
-		elsif($opt->{expires} =~ /^\s*(\d+)\s*[mhdw]/) {
-			my $adder = Vend::Config::time_to_seconds($opt->{expires});
-			@date_expires = localtime($now + $adder);
+		elsif($opt->{expires} =~ /^\s*(\d+)\s*[mhdwy]/) {
+			@date_expires = localtime(adjust_time($opt->{expires}, $now));
 		}
 		elsif($opt->{expires}) {
-			::logError("Expiration date '%s' not understood, ingoring.", $opt->{expires});
+			::logError("Expiration date '%s' not understood, ignoring.", $opt->{expires});
 		}
 
 		if(@date_expires) {



2.313                interchange/lib/Vend/Interpolate.pm


rev 2.313, prev_rev 2.312
Index: Interpolate.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Interpolate.pm,v
retrieving revision 2.312
retrieving revision 2.313
diff -u -r2.312 -r2.313
--- Interpolate.pm	23 Mar 2009 13:39:50 -0000	2.312
+++ Interpolate.pm	1 May 2009 13:50:00 -0000	2.313
@@ -1,6 +1,6 @@
 # Vend::Interpolate - Interpret Interchange tags
 # 
-# $Id: Interpolate.pm,v 2.312 2009-03-23 13:39:50 mheins Exp $
+# $Id: Interpolate.pm,v 2.313 2009-05-01 13:50:00 pajamian Exp $
 #
 # Copyright (C) 2002-2008 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -28,7 +28,7 @@
 require Exporter;
 @ISA = qw(Exporter);
 
-$VERSION = substr(q$Revision: 2.312 $, 10);
+$VERSION = substr(q$Revision: 2.313 $, 10);
 
 @EXPORT = qw (
 
@@ -2087,22 +2087,19 @@
 	my $now = $opt->{time} || time();
 	$fmt = '%Y%m%d' if $opt->{sortable};
 
-	if($opt->{adjust}) {
-		my $neg = $opt->{adjust} =~ s/^\s*-\s*//;
-		my $diff;
-		$opt->{adjust} =~ s/^\s*\+\s*//;
-		if($opt->{hours}) {
-			$diff = (60 * 60) * ($opt->{adjust} || $opt->{hours});
-		}
-		elsif($opt->{adjust} !~ /[A-Za-z]/) {
-			$opt->{adjust} =~ s:(\d+)(\d[05])$:$1 + $2 / 60:e;
-			$opt->{adjust} =~ s/00$//;
-			$diff = (60 * 60) * $opt->{adjust};
+	if($opt->{adjust} || $opt->{hours}) {
+		my $adjust = $opt->{adjust};
+		if ($opt->{hours}) {
+			$adjust ||= $opt->{hours};
+			$adjust .= ' hours';
 		}
-		else {
-			$diff = Vend::Config::time_to_seconds($opt->{adjust});
+
+		elsif ($adjust !~ /[A-Za-z]/) {
+			$adjust =~ s/(?<=\d)(\d[05])// and $adjust += $1 / 60;
+			$adjust .= ' hours';
 		}
-		$now = $neg ? $now - $diff : $now + $diff;
+
+		$now = adjust_time($adjust, $now, $opt->{compensate_dst});
 	}
 
 	$fmt ||= $opt->{format} || $opt->{fmt} || '%c';



2.66                 interchange/lib/Vend/UserDB.pm


rev 2.66, prev_rev 2.65
Index: UserDB.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/UserDB.pm,v
retrieving revision 2.65
retrieving revision 2.66
diff -u -r2.65 -r2.66
--- UserDB.pm	18 Mar 2009 00:39:21 -0000	2.65
+++ UserDB.pm	1 May 2009 13:50:01 -0000	2.66
@@ -1,6 +1,6 @@
 # Vend::UserDB - Interchange user database functions
 #
-# $Id: UserDB.pm,v 2.65 2009-03-18 00:39:21 markj Exp $
+# $Id: UserDB.pm,v 2.66 2009-05-01 13:50:01 pajamian Exp $
 #
 # Copyright (C) 2002-2008 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -17,7 +17,7 @@
 
 package Vend::UserDB;
 
-$VERSION = substr(q$Revision: 2.65 $, 10);
+$VERSION = substr(q$Revision: 2.66 $, 10);
 
 use vars qw!
 	$VERSION
@@ -598,9 +598,7 @@
 	my ($self, $loc, %options) = @_;
 	return undef unless $self->{OPTIONS}{location};
 	if($options{mode} =~ /^\s*expires?\s+(.*)/i) {
-		my $secs = Vend::Config::time_to_seconds($1);
-		my $now = time();
-		$options{mode} = $secs + $now;
+		$options{mode} = adjust_time($1);
 	}
 	my $acl = $self->{DB}->field( $self->{USERNAME}, $loc );
 	my $f = $ready->reval($acl) || {};



2.127                interchange/lib/Vend/Util.pm


rev 2.127, prev_rev 2.126
Index: Util.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Util.pm,v
retrieving revision 2.126
retrieving revision 2.127
diff -u -r2.126 -r2.127
--- Util.pm	30 Apr 2009 03:50:21 -0000	2.126
+++ Util.pm	1 May 2009 13:50:01 -0000	2.127
@@ -1,6 +1,6 @@
 # Vend::Util - Interchange utility functions
 #
-# $Id: Util.pm,v 2.126 2009-04-30 03:50:21 mheins Exp $
+# $Id: Util.pm,v 2.127 2009-05-01 13:50:01 pajamian Exp $
 # 
 # Copyright (C) 2002-2008 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -34,6 +34,7 @@
 @ISA = qw(Exporter);
 
 @EXPORT = qw(
+	adjust_time
 	catfile
 	check_security
 	copyref
@@ -96,7 +97,7 @@
 use Vend::File;
 use subs qw(logError logGlobal);
 use vars qw($VERSION @EXPORT @EXPORT_OK);
-$VERSION = substr(q$Revision: 2.126 $, 10);
+$VERSION = substr(q$Revision: 2.127 $, 10);
 
 my $Eval_routine;
 my $Eval_routine_file;
@@ -1889,8 +1890,7 @@
     # Set expire to now + some time if expire string is something like
     # "30 days" or "7 weeks" or even "60 minutes"
 	if($expire =~ /^\s*\d+[\s\0]*[A-Za-z]\S*\s*$/) {
-		my $add = Vend::Config::time_to_seconds($expire);
-		$expire = time() + $add if $add;
+	    $expire = adjust_time($expire);
 	}
 
 	if (! $::Instance->{Cookies}) {
@@ -2271,6 +2271,104 @@
 	return unpack('N',$rtime);
 }
 
+#
+# Adjusts a unix time stamp (2nd arg) by the amount specified in the first arg.  First arg should be
+# a number (signed integer or float) followed by one of second(s), minute(s), hour(s), day(s)
+# week(s) month(s) or year(s).  Second arg defaults to the current time.  If the third arg is true
+# the time will be compensated for daylight savings time (so that an adjustment of 6 months will
+# still cause the same time to be displayed, even if it is transgressing the DST boundary).
+#
+# This will accept multiple adjustments strung together, so you can do: "-5 days, 2 hours, 6 mins"
+# and the time will have thost amounts subtracted from it.  You can also add and subtract in the
+# same line, "+2 years -3 days".  If you specify a sign (+ or -) then that sign will remain in
+# effect until a new sign is specified on the line (so you can do,
+# "+5 years, 6 months, 3 days, -4 hours, 7 minutes").  The comma (,) between adjustments is
+# optional.
+#
+sub adjust_time {
+    my ($adjust, $time, $compensate_dst) = @_;
+    $time ||= time;
+
+    unless ($adjust =~ /^(?:\s*[+-]?\s*[\d\.]+\s*[a-z]*\s*,?)+$/i) {
+	::logError("adjust_time(): bad format: $adjust");
+	return $time;
+    }
+
+    # @times: 0: sec, 1: min, 2: hour, 3: day, 4: month, 5: year, 8: isdst
+    # 6,7: dow and doy, but mktime ignores these (and so do we).
+
+    # A note about isdst: localtime returns 1 if returned time is adjusted for dst and 0 otherwise.
+    # mktime expects the same, but if this is set to -1 mktime will determine if the date should be
+    # dst adjusted according to dst rules for the current timezone.  The way that we use this is we
+    # leave it set to the return value from locatime and we end up with a time that is adjusted by
+    # an absolute amount (so if you adjust by six months the actual time returned may be different
+    # but only because of DST).  If we want mktime to compensate for dst then we set this to -1 and
+    # mktime will make the appropriate adjustment for us (either add one hour or subtract one hour
+    # or leave the time the same).
+
+    my @times = localtime($time);
+    my $sign = 1;
+
+    foreach my $amount ($adjust =~ /([+-]?\s*[\d\.]+\s*[a-z]*)/ig) {
+	my $unit = 'seconds';
+	$amount =~ s/\s+//g;
+
+	if ($amount =~ s/^([+-])//)   { $sign = $1 eq '+' ? 1 : -1 }
+	if ($amount =~ s/([a-z]+)$//) { $unit = lc $1 }
+	$amount *= $sign;
+
+	# A week is simply 7 days.
+	if ($unit =~ /^w/) {
+	    $unit = 'days';
+	    $amount *= 7;
+	}
+
+	if ($unit =~ /^s/) { $times[0] += $amount }
+	elsif ($unit =~ /^mo/) { $times[4] += $amount } # has to come before min
+	elsif ($unit =~ /^m/) { $times[1] += $amount }
+	elsif ($unit =~ /^h/) { $times[2] += $amount }
+	elsif ($unit =~ /^d/) { $times[3] += $amount }
+	elsif ($unit =~ /^y/) { $times[5] += $amount }
+
+	else {
+	    ::logError("adjust_time(): bad unit: $unit");
+	    return $time;
+	}
+    }
+
+    if ($compensate_dst) { $times[8] = -1 }
+
+    # mktime can only handle integers, so we need to convert real numbers:
+    my @multip = (0, 60, 60, 24, 0, 12);
+    my $monfrac = 0;
+    foreach my $i (reverse 0..5) {
+	if ($times[$i] =~ /\./) {
+	    if ($multip[$i]) {
+		$times[$i-1] += ($times[$i] - int $times[$i]) * $multip[$i];
+	    }
+
+	    elsif ($i == 4) {
+		# Fractions of a month need some really extra special handling.
+		$monfrac = $times[$i] - int $times[$i];
+	    }
+
+	    $times[$i] = int $times[$i]
+	}
+    }
+
+    $time = POSIX::mktime(@times);
+
+    # This is how we handle a fraction of a month:
+    if ($monfrac) {
+	$times[4] += $monfrac > 0 ? 1 : -1;
+	my $timediff = POSIX::mktime(@times);
+	$timediff = int(abs($timediff - $time) * $monfrac);
+	$time += $timediff;
+    }
+
+    return $time;
+}
+
 sub backtrace {
     my $msg = "Backtrace:\n\n";
     my $frame = 1;







More information about the interchange-cvs mailing list