Article View: gnu.emacs.vm.bug
Article #852[PATCH] teach VM about ISO-8601 dates
From: Tkil
Date: Wed, 12 Mar 2003 05:14
Date: Wed, 12 Mar 2003 05:14
164 lines
7908 bytes
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-mailShow 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