🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.vm.bug
Article #852

[PATCH] teach VM about ISO-8601 dates

#852
From: Tkil
Date: Wed, 12 Mar 2003 05:14
164 lines
7908 bytes
[This is a repost (try 4!), when I didn't see my original make it off
my leaf node after about a day.  Apologies to anyone who sees this
more than once!]

Getting frustrated after the Nth time I couldn't remember the date
format that the "sent-before" selector wanted, I decided I'd teach VM
about ISO-8601 (YYYY-MM-DD) date formats.

Believing that anything worth doing is worth overdoing, I worked up
the following patch.  It works fine on my (quite recent) XEmacs
installation; it's entirely possible, if not outright probable, that I
am using features that are nonportable or unstable.  

I also feel that I don't fully understand the cosequences of some of
my changes.  Am I handling errors the way that the old code did?  Is
my code too slow on a frequently-used path?  Are there functions
elsewhere in X?Emacs that would do all this for us?

Anyway, consider this up for discussion at least.  :)

Thanks,
t.

diff -ur vm-7.11-orig/vm-summary.el vm-7.11/vm-summary.el
--- vm-7.11-orig/vm-summary.el	2003-03-11 01:37:59.000000000 -0700
+++ vm-7.11/vm-summary.el	2003-03-11 03:24:12.000000000 -0700
@@ -790,6 +790,115 @@
 		 (match-end 1)))))))))
 
 (defun vm-parse-date (date)
+  (or (vm-parse-date-rfc822 date)
+      (vm-parse-date-iso8601 date)
+      (vm-parse-date-ctime date)
+      (vm-parse-date-flexible date)))
+
+(defun vm-parse-date-guess-year (year)
+  (let* ((year-int (string-to-int year))
+         (prefix   (cond ((< year-int  70) "20")
+                         ((< year-int 100) "19"))))
+    (concat prefix year)))
+
+(defun vm-parse-date-get-substring (date num)
+  (let ((b (match-beginning num))
+        (e (match-end num)))
+    (if (and (integerp b)
+             (integerp e))
+        (substring date b e)
+      "")))
+
+(defconst vm-parse-date-rfc822-re
+  (let ((abbrev "[a-z][a-z][a-z]")      ; month and day abbrevs
+        (ws     "[ \t\n]*")             ; white space
+        (wsd    "[ \t\n---]*"))         ; white space or dashes
+    (concat
+     "^"
+     "\\(\\(" abbrev "\\),\\)?" ws      ; day of week (optional) [subexpr 1, 2]
+     "\\([0-9][0-9]?\\)" wsd            ; day of month [3]
+     "\\(" abbrev "\\)" wsd             ; month abbreviation [4]
+     "\\([0-9]*[0-9][0-9]\\)" ws        ; optional century + year [5]
+     "\\([0-9:]+\\)" ws                 ; time [6]
+     "\\([a-z][a-z]?[a-z]?"             ; time zone (name or offset) [7]
+        "\\|"
+        "[+---][01][0-9][0-9][0-9]\\)"
+     "$"))
+  "Regular expression used to parse RFC 822 formatted dates")
+
+(defun vm-parse-date-rfc822 (date)
+  (if (string-match vm-parse-date-rfc822-re date)
+      (let ((weekday  (vm-parse-date-get-substring date 2))
+            (monthday (vm-parse-date-get-substring date 3))
+            (month    (vm-parse-date-get-substring date 4))
+            (year     (vm-parse-date-get-substring date 5))
+            (hour     (vm-parse-date-get-substring date 6))
+            (timezone (vm-parse-date-get-substring date 7))
+            (year-len (- (match-end 5) (match-beginning 5))))
+        (if (= year-len 2) (setq year (vm-parse-date-guess-year year)))
+        (vector weekday monthday month year hour timezone))))
+
+(defconst vm-parse-date-iso8601-re
+  (let ((dd "[0-9][0-9]"))              ; two digits
+    (concat
+     "^"
+     "\\(" dd dd "\\|" dd "\\)-?"       ; year [1]
+     "\\(\\(" dd "\\)-?\\)?"            ; month [3]
+     "\\(\\(" dd "\\)[ \tTt]?\\)?"      ; day [5]
+     "\\(\\(" dd "\\):?\\)?"            ; hours [7]
+     "\\(\\(" dd "\\):?\\)?"            ; minutes [9]
+     "\\("    dd "\\)?[ \t]?"           ; seconds [10]
+     "\\(Z\\|"                          ; timezone [11]
+        "[+---]" dd "\\|"
+        "[+---]" dd dd "\\)?"
+     "$"))
+  "Regular expression used to parse ISO-8601 formatted dates")
+
+(defconst vm-parse-date-month-names
+  [ "jan" "feb" "mar" "apr" "may" "jun" "jul" "aug" "sep" "oct" "nov" "dec" ]
+  "timezone can only handle text month names.  Sigh.")
+
+(defun vm-parse-date-iso8601 (date)
+  (if (string-match vm-parse-date-iso8601-re date)
+      (let ((weekday  "")
+            (year     (vm-parse-date-get-substring date 1))
+            (monthnum (- (string-to-int (vm-parse-date-get-substring date 3)) 1))
+            (monthday (vm-parse-date-get-substring date 5))
+            (hour     (vm-parse-date-get-substring date 7))
+            (timezone (vm-parse-date-get-substring date 11))
+            (year-len (- (match-end 1) (match-beginning 1))))
+        (if (= year-len 2) (setq year (vm-parse-date-guess-year year)))
+        (vector weekday monthday (aref vm-parse-date-month-names monthnum)
+                year hour timezone))))
+
+(defconst vm-parse-date-ctime-re
+  (let ((abbrev "[a-z][a-z][a-z]")      ; month and day abbrevs
+        (ws     "[ \t\n]*"))            ; whitespace
+    (concat 
+     "^"
+     "\\(" abbrev "\\)" ws              ; weekday [1]
+     "\\(" abbrev "\\)" ws              ; month [2]
+     "\\([0-9][0-9]?\\)" ws             ; monthday [3]
+     "\\([0-9:]+\\)" ws                 ; hour [4]
+     "\\([0-9][0-9][0-9][0-9]\\)" ws    ; year [5]
+     "\\([a-z][a-z]?[a-z]?\\|"          ; timezone [6]
+        "[+---][01][0-9][0-9][0-9]\\)?"
+     "$"))
+  "Regular expression used to parse `ctime(3)' formatted dates")
+
+(defun vm-parse-date-ctime (date)
+  (if (string-match vm-parse-date-ctime-re date)
+      (let ((weekday  (vm-parse-date-get-substring date 1))
+            (month    (vm-parse-date-get-substring date 2))
+            (monthday (vm-parse-date-get-substring date 3))
+            (hour     (vm-parse-date-get-substring date 4))
+            (year     (vm-parse-date-get-substring date 5))
+            (timezone (vm-parse-date-get-substring date 6))
+            (year-len (- (match-end 5) (match-beginning 5))))
+        (if (= year-len 2) (setq year (vm-parse-date-guess-year year)))
+        (vector weekday monthday month year hour timezone))))
+
+(defun vm-parse-date-flexible (date)
   (let ((weekday "")
 	(monthday "")
 	(month "")
@@ -821,18 +930,9 @@
 		  (<= (length string) 2))
 	     (setq monthday string))
 	    ((= (length string) 2)
-	     (if (< (string-to-int string) 70)
-		 (setq year (concat "20" string))
-	       (setq year (concat "19" string))))
+	     (setq year (vm-parse-date-guess-year year)))
 	    (t (setq year string))))
-    
-    (aset vm-parse-date-workspace 0 weekday)
-    (aset vm-parse-date-workspace 1 monthday)
-    (aset vm-parse-date-workspace 2 month)
-    (aset vm-parse-date-workspace 3 year)
-    (aset vm-parse-date-workspace 4 hour)
-    (aset vm-parse-date-workspace 5 timezone)
-    vm-parse-date-workspace))
+    (vector weekday monthday month year hour timezone)))
 
 (defun vm-su-do-date (m)
   (let ((case-fold-search t)
Technical Details
Message-ID: <gwuj5jhdd.fsf@brand.scrye.com>
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!newsfeed.berkeley.edu!news-hog.berkeley.edu!ucberkeley!nntp-relay.ihug.net!ihug.co.nz!news.compaq.com!newsfeed.frii.net!newsfeed.frii.net!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f6829,609808896b8b38e8,start
X-Google-Attributes: gidf6829,public
X-Google-ArrivalTime: 2003-03-11 21:15:25 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news1.google.com!newsfeed.stanford.edu!newsfeed.berkeley.edu!news-hog.berkeley.edu!ucberkeley!nntp-relay.ihug.net!ihug.co.nz!news.compaq.com!newsfeed.frii.net!newsfeed.frii.net!not-for-mail
From: Tkil <tkil@scrye.com>
Newsgroups: gnu.emacs.vm.bug
Subject: [PATCH] teach VM about ISO-8601 dates
Date: 11 Mar 2003 22:14:54 -0700
Organization: Scrye.com
Sender: tkil@brand.scrye.com
Message-ID: <gwuj5jhdd.fsf@brand.scrye.com>
Reply-To: Tkil <tkil@scrye.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Complaints-To: news@brand.scrye.com
X-Attribution: Tkil
User-Agent: Gnus/5.0808 (Gnus v5.8.8) XEmacs/21.4 (Honest Recruiter)
Lines: 164
NNTP-Posting-Host: 216.17.180.1
X-Trace: 1047446124 news.frii.net 194 216.17.180.1