Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: relative calendar times and summer time



I'm not sure I really need to post this, but just in case you
thought calculating dates was easy, see the long comment in the
patch below.  Then there are a few minor related oddments.

Index: Functions/Calendar/calendar_scandate
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Calendar/calendar_scandate,v
retrieving revision 1.3
diff -u -r1.3 calendar_scandate
--- Functions/Calendar/calendar_scandate	31 Jan 2007 16:53:39 -0000	1.3
+++ Functions/Calendar/calendar_scandate	22 Mar 2007 23:48:35 -0000
@@ -188,7 +188,7 @@
 # line[time_start,time_end] is the string for the time.
 integer time_start time_end date_start date_end
 integer anchor anchor_end debug setvar
-integer relative relative_start reladd reldate relsign=1
+integer relative relative_start reladd reldate relsign=1 newadd h1 h2 hd
 
 while getopts "aAdmrR:st" opt; do
   case $opt in
@@ -583,8 +583,8 @@
        if (( day > 28 )); then
 	 while true; do
 	   strftime -s day2 "%d" $reldate
-	   # There are only up to 3 days in it, so just wind back one at a time.
-	   # Saves counting.
+	   # There are only up to 3 days in it, so just wind back one at a
+           # time.  Saves counting.
 	   (( day2 >= 28 )) && break
 	   (( reldate -= daysecs ))
 	 done
@@ -623,13 +623,73 @@
   fi
   if [[ $line = (#bi)${~dspat}(<->|)[[:space:]]#(w|wk|week|weekly)${~repat} ]]; then
      [[ -z $match[2] ]] && match[2]=1
-     (( reladd += relsign * 7 * daysecs * ${match[2]} ))
+     (( newadd = relsign * 7 * daysecs * ${match[2]} ))
+     if (( relative == 2 )); then
+       # See explanation of this correction under days, below.
+       strftime -s h1 "%H" $(( relative_start + reladd ))
+       strftime -s h2 "%H" $(( relative_start + reladd + newadd ))
+       (( hd = h2 - h1 ))
+       # and of course we might go past midnight...
+       if (( hd > 12 )); then
+	   (( hd -= 24 ))
+       elif (( hd < -12 )); then
+	   (( hd += 24 ))
+       fi
+       (( newadd -= hd * 3600 ))
+     fi
+     (( reladd += newadd ))
      line=${line[1,$mbegin[2]-1]}${line[$mend[4]+1,-1]}
      time_found=1
   fi
   if [[ $line = (#bi)${~dspat}(<->|)[[:space:]]#(d|dy|day|daily)${~repat} ]]; then
      [[ -z $match[2] ]] && match[2]=1
-     (( reladd += relsign * daysecs * ${match[2]} ))
+     (( newadd = relsign * daysecs * ${match[2]} ))
+     if (( relative == 2 )); then
+       # You thought a day was always the same time?  Ho, ho, ho.
+       # If the clocks go forward or back, we can gain or lose
+       # an hour.  Check this by seeing what the hour is before
+       # and after adding the number of days.  If it changes,
+       # remove the difference.
+       # 
+       # We need this correction for weeks, too, as above.
+       # (We could apply corrections for weeks and days together,
+       # in fact, but I've left it a little more modular).
+       # We don't need it for years and months because we calculated
+       # those by actually looking at the calendar for a given
+       # time of day, so the adjustment came out in the wash.
+       # We don't need it for hours or smaller periods because
+       # presumably if a user asks for something in 3 hours time
+       # they don't mean 4 hours if the clocks went back and
+       # 2 hours if they went forward.  At least, I think so.
+       # Consider:
+       #   % calendar_showdate +2d,1hr
+       #   Sun Mar 25 00:37:00 GMT 2007
+       #   % calendar_showdate +2d,2hr
+       #   Sun Mar 25 02:37:09 BST 2007
+       # At first sight that looks wrong because the clock appears
+       # to jump two hours.  (Yes, it took me all of 9 seconds to
+       # edit the line.)  But actually it's only jumped the hour
+       # you asked for, because one is in GMT and the other in BST.
+       # In principle you could say the same thing about days:
+       # Sun Mar 25 00:00:00 GMT 2007  and  Mon Mar 26 01:00:00 BST 2007
+       # are a day apart.  But usually if you say "same time next Tuesday"
+       # you mean "when the clock says the same time, even if someone
+       # has nipped in and adjusted it in the mean time", although
+       # for some reason you don't usually bother saying that.
+       #
+       # Hope that's clear.
+       strftime -s h1 "%H" $(( relative_start + reladd ))
+       strftime -s h2 "%H" $(( relative_start + reladd + newadd ))
+       (( hd = h2 - h1 ))
+       # and of course we might go past midnight...
+       if (( hd > 12 )); then
+	   (( hd -= 24 ))
+       elif (( hd < -12 )); then
+	   (( hd += 24 ))
+       fi
+       (( newadd -= hd * 3600 ))
+     fi
+     (( reladd += newadd ))
      line=${line[1,$mbegin[2]-1]}${line[$mend[4]+1,-1]}
      time_found=1
   fi
@@ -661,7 +721,8 @@
       fi
     fi
     # relative_start is zero if we're not using it
-    (( REPLY = relative_start + reladd + (hour * 60 + minute) * 60 + second ))
+    (( reladd += (hour * 60 + minute) * 60 + second ))
+    (( REPLY = relative_start + reladd  ))
     [[ -n $setvar ]] && REPLY2=$line
     return 0
   fi
Index: Functions/Calendar/calendar_showdate
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Calendar/calendar_showdate,v
retrieving revision 1.1
diff -u -r1.1 calendar_showdate
--- Functions/Calendar/calendar_showdate	31 Jan 2007 16:53:40 -0000	1.1
+++ Functions/Calendar/calendar_showdate	22 Mar 2007 23:48:35 -0000
@@ -1,19 +1,24 @@
 emulate -L zsh
 setopt extendedglob
+zmodload -i zsh/datetime
 
-local optm datefmt
+local optm datefmt opt
 integer optr replyset
 
 zstyle -s ':datetime:calendar_showdate:' date-format datefmt ||
   datefmt="%a %b %d %H:%M:%S %Z %Y"
 
-if [[ $1 = -r ]]; then
-  shift
-  REPLY=0
-  optr=1
-else
-  local REPLY
-fi
+while [[ $argv[$OPTIND] != +* ]] && getopts "r" opt; do
+  case $opt in
+    (r)
+    REPLY=0
+    optr=1
+    ;;
+  esac
+done
+shift $(( OPTIND - 1 ))
+
+(( optr )) || local REPLY
 
 if (( ! $# )); then
   print "Usage: $0 datespec [ ... ]" >&2


-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author