gitweb.js: Extract and improve datetime handling

Move formatDateISOLocal(epoch, timezone) function (and also helper timezoneOffset(timezoneInfo) function it requires) from common-lib.js to datetime.js Add new functions: * localTimezoneOffset - to get browser timezone offset in seconds * localTimezoneInfo - to get browser timezone in '(+|-)HHMM' format * formatTimezoneInfo - turn offset in hours and minutes into '(+|-)HHMM' * parseRFC2822Date - to parse RFC-2822 dates that gitweb uses into epoch * formatDateRFC2882 - like formatDateISOLocal, only RFC-2822 format All those functions are meant to be used in future commit 'gitweb: javascript ability to adjust time based on timezone' An alternative would be to use e.g. Datejs (http://www.datejs.com) library, or JavaScript framework that has date formatting (perhaps as a plugin). While at it escape '-' in character class inside tzRe regexp, as recommended by JSLint (http://www.jslint.com). Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jakub Narebski committed Apr 28, 2011 at 21:04 UTC 54b1479a770b240d71bbd000fb40e470987bac59
3 files changed +162 -51
gitweb/Makefile
+1
@@ -117,6 +117,7 @@ GITWEB_FILES += static/git-logo.png static/git-favicon.png
117 # js/lib/common-lib.js should be always first, then js/lib/*.js,
118 # then the rest of files; js/gitweb.js should be last (if it exists)
119 GITWEB_JSLIB_FILES += static/js/lib/common-lib.js
120 +GITWEB_JSLIB_FILES += static/js/lib/datetime.js
121 GITWEB_JSLIB_FILES += static/js/javascript-detection.js
122 GITWEB_JSLIB_FILES += static/js/blame_incremental.js
123
gitweb/static/js/lib/common-lib.js
-51
@@ -88,57 +88,6 @@ function createRequestObject() {
88 }
89
90
91 -/* ............................................................ */
92 -/* time and data */
93 -
94 -/**
95 - * used to extract hours and minutes from timezone info, e.g '-0900'
96 - * @constant
97 - */
98 -var tzRe = /^([+-])([0-9][0-9])([0-9][0-9])$/;
99 -
100 -/**
101 - * convert numeric timezone +/-ZZZZ to offset from UTC in seconds
102 - *
103 - * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
104 - * @returns {Number} offset from UTC in seconds for timezone
105 - *
106 - * @globals tzRe
107 - */
108 -function timezoneOffset(timezoneInfo) {
109 - var match = tzRe.exec(timezoneInfo);
110 - var tz_sign = (match[1] === '-' ? -1 : +1);
111 - var tz_hour = parseInt(match[2],10);
112 - var tz_min = parseInt(match[3],10);
113 -
114 - return tz_sign*(((tz_hour*60) + tz_min)*60);
115 -}
116 -
117 -/**
118 - * return date in local time formatted in iso-8601 like format
119 - * 'yyyy-mm-dd HH:MM:SS +/-ZZZZ' e.g. '2005-08-07 21:49:46 +0200'
120 - *
121 - * @param {Number} epoch: seconds since '00:00:00 1970-01-01 UTC'
122 - * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
123 - * @returns {String} date in local time in iso-8601 like format
124 - */
125 -function formatDateISOLocal(epoch, timezoneInfo) {
126 - // date corrected by timezone
127 - var localDate = new Date(1000 * (epoch +
128 - timezoneOffset(timezoneInfo)));
129 - var localDateStr = // e.g. '2005-08-07'
130 - localDate.getUTCFullYear() + '-' +
131 - padLeft(localDate.getUTCMonth()+1, 2, '0') + '-' +
132 - padLeft(localDate.getUTCDate(), 2, '0');
133 - var localTimeStr = // e.g. '21:49:46'
134 - padLeft(localDate.getUTCHours(), 2, '0') + ':' +
135 - padLeft(localDate.getUTCMinutes(), 2, '0') + ':' +
136 - padLeft(localDate.getUTCSeconds(), 2, '0');
137 -
138 - return localDateStr + ' ' + localTimeStr + ' ' + timezoneInfo;
139 -}
140 -
141 -
91 /* ............................................................ */
92 /* unquoting/unescaping filenames */
93
gitweb/static/js/lib/datetime.js new
+161
@@ -0,0 +1,161 @@
1 +// Copyright (C) 2007, Fredrik Kuivinen <frekui@gmail.com>
2 +// 2007, Petr Baudis <pasky@suse.cz>
3 +// 2008-2011, Jakub Narebski <jnareb@gmail.com>
4 +
5 +/**
6 + * @fileOverview Datetime manipulation: parsing and formatting
7 + * @license GPLv2 or later
8 + */
9 +
10 +
11 +/* ............................................................ */
12 +/* parsing and retrieving datetime related information */
13 +
14 +/**
15 + * used to extract hours and minutes from timezone info, e.g '-0900'
16 + * @constant
17 + */
18 +var tzRe = /^([+\-])([0-9][0-9])([0-9][0-9])$/;
19 +
20 +/**
21 + * convert numeric timezone +/-ZZZZ to offset from UTC in seconds
22 + *
23 + * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
24 + * @returns {Number} offset from UTC in seconds for timezone
25 + *
26 + * @globals tzRe
27 + */
28 +function timezoneOffset(timezoneInfo) {
29 + var match = tzRe.exec(timezoneInfo);
30 + var tz_sign = (match[1] === '-' ? -1 : +1);
31 + var tz_hour = parseInt(match[2],10);
32 + var tz_min = parseInt(match[3],10);
33 +
34 + return tz_sign*(((tz_hour*60) + tz_min)*60);
35 +}
36 +
37 +/**
38 + * return local (browser) timezone as offset from UTC in seconds
39 + *
40 + * @returns {Number} offset from UTC in seconds for local timezone
41 + */
42 +function localTimezoneOffset() {
43 + // getTimezoneOffset returns the time-zone offset from UTC,
44 + // in _minutes_, for the current locale
45 + return ((new Date()).getTimezoneOffset() * -60);
46 +}
47 +
48 +/**
49 + * return local (browser) timezone as numeric timezone '(+|-)HHMM'
50 + *
51 + * @returns {String} locat timezone as -/+ZZZZ
52 + */
53 +function localTimezoneInfo() {
54 + var tzOffsetMinutes = (new Date()).getTimezoneOffset() * -1;
55 +
56 + return formatTimezoneInfo(0, tzOffsetMinutes);
57 +}
58 +
59 +
60 +/**
61 + * Parse RFC-2822 date into a Unix timestamp (into epoch)
62 + *
63 + * @param {String} date: date in RFC-2822 format, e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'
64 + * @returns {Number} epoch i.e. seconds since '00:00:00 1970-01-01 UTC'
65 + */
66 +function parseRFC2822Date(date) {
67 + // Date.parse accepts the IETF standard (RFC 1123 Section 5.2.14 and elsewhere)
68 + // date syntax, which is defined in RFC 2822 (obsoletes RFC 822)
69 + // and returns number of _milli_seconds since January 1, 1970, 00:00:00 UTC
70 + return Date.parse(date) / 1000;
71 +}
72 +
73 +
74 +/* ............................................................ */
75 +/* formatting date */
76 +
77 +/**
78 + * format timezone offset as numerical timezone '(+|-)HHMM' or '(+|-)HH:MM'
79 + *
80 + * @param {Number} hours: offset in hours, e.g. 2 for '+0200'
81 + * @param {Number} [minutes] offset in minutes, e.g. 30 for '-4030';
82 + * it is split into hours if not 0 <= minutes < 60,
83 + * for example 1200 would give '+0100';
84 + * defaults to 0
85 + * @param {String} [sep] separator between hours and minutes part,
86 + * default is '', might be ':' for W3CDTF (rfc-3339)
87 + * @returns {String} timezone in '(+|-)HHMM' or '(+|-)HH:MM' format
88 + */
89 +function formatTimezoneInfo(hours, minutes, sep) {
90 + minutes = minutes || 0; // to be able to use formatTimezoneInfo(hh)
91 + sep = sep || ''; // default format is +/-ZZZZ
92 +
93 + if (minutes < 0 || minutes > 59) {
94 + hours = minutes > 0 ? Math.floor(minutes / 60) : Math.ceil(minutes / 60);
95 + minutes = Math.abs(minutes - 60*hours); // sign of minutes is sign of hours
96 + // NOTE: this works correctly because there is no UTC-00:30 timezone
97 + }
98 +
99 + var tzSign = hours >= 0 ? '+' : '-';
100 + if (hours < 0) {
101 + hours = -hours; // sign is stored in tzSign
102 + }
103 +
104 + return tzSign + padLeft(hours, 2, '0') + sep + padLeft(minutes, 2, '0');
105 +}
106 +
107 +/**
108 + * return date in local time formatted in iso-8601 like format
109 + * 'yyyy-mm-dd HH:MM:SS +/-ZZZZ' e.g. '2005-08-07 21:49:46 +0200'
110 + *
111 + * @param {Number} epoch: seconds since '00:00:00 1970-01-01 UTC'
112 + * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
113 + * @returns {String} date in local time in iso-8601 like format
114 + */
115 +function formatDateISOLocal(epoch, timezoneInfo) {
116 + // date corrected by timezone
117 + var localDate = new Date(1000 * (epoch +
118 + timezoneOffset(timezoneInfo)));
119 + var localDateStr = // e.g. '2005-08-07'
120 + localDate.getUTCFullYear() + '-' +
121 + padLeft(localDate.getUTCMonth()+1, 2, '0') + '-' +
122 + padLeft(localDate.getUTCDate(), 2, '0');
123 + var localTimeStr = // e.g. '21:49:46'
124 + padLeft(localDate.getUTCHours(), 2, '0') + ':' +
125 + padLeft(localDate.getUTCMinutes(), 2, '0') + ':' +
126 + padLeft(localDate.getUTCSeconds(), 2, '0');
127 +
128 + return localDateStr + ' ' + localTimeStr + ' ' + timezoneInfo;
129 +}
130 +
131 +/**
132 + * return date in local time formatted in rfc-2822 format
133 + * e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'
134 + *
135 + * @param {Number} epoch: seconds since '00:00:00 1970-01-01 UTC'
136 + * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
137 + * @param {Boolean} [padDay] e.g. 'Sun, 07 Aug' if true, 'Sun, 7 Aug' otherwise
138 + * @returns {String} date in local time in rfc-2822 format
139 + */
140 +function formatDateRFC2882(epoch, timezoneInfo, padDay) {
141 + // A short textual representation of a month, three letters
142 + var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
143 + // A textual representation of a day, three letters
144 + var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
145 + // date corrected by timezone
146 + var localDate = new Date(1000 * (epoch +
147 + timezoneOffset(timezoneInfo)));
148 + var localDateStr = // e.g. 'Sun, 7 Aug 2005' or 'Sun, 07 Aug 2005'
149 + days[localDate.getUTCDay()] + ', ' +
150 + (padDay ? padLeft(localDate.getUTCDate(),2,'0') : localDate.getUTCDate()) + ' ' +
151 + months[localDate.getUTCMonth()] + ' ' +
152 + localDate.getUTCFullYear();
153 + var localTimeStr = // e.g. '21:49:46'
154 + padLeft(localDate.getUTCHours(), 2, '0') + ':' +
155 + padLeft(localDate.getUTCMinutes(), 2, '0') + ':' +
156 + padLeft(localDate.getUTCSeconds(), 2, '0');
157 +
158 + return localDateStr + ' ' + localTimeStr + ' ' + timezoneInfo;
159 +}
160 +
161 +/* end of datetime.js */