Login

Client-side Django-style date & time string formatting

Author:
robbie
Posted:
March 6, 2007
Language:
JavaScript
Version:
Not specified
Score:
3 (after 3 ratings)

This is a reasonably straight forward port of functionality provided by the django.utils.dateformat module into a method extending JavaScript's Date object. Its intended use is to allow client-side dynamic content to share the same date & time string formatting as Django template markup. By using this in conjunction with a context processor (to pass a format string to all templates) you can switch formats for both server-generated & client-generated dates across a complete site with a single setting.

The function supports almost the entire format -- as listed by the Django documentation for the now template tag -- with the exception of "I" & "T".

As a 'dumb' illustration, the following template tag usage:

It is {% now "jS F Y H:i" %}

...could equate to the following:

It is <script type="text/javascript">var now = new Date(); document.write(now.strfdate('jS F Y H:i'));</script>

It's not extensively tested (I only wrote it over the weekend), but seems to be working okay. Feel free to leave any corrections or suggestions in the comments, and I'll try to keep this entry updated if I make any fixes or changes.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
String.prototype.zfill = function (width){
	var str = '' + this;
	while (str.length < width) str = '0' + str;
	return str;
}

Date.prototype.strfdate = function (format){
	var dt = this;
	
	var year = dt.getFullYear();
	var month = dt.getMonth();
	var date = dt.getDate();
	var hours = dt.getHours();
	var minutes = dt.getMinutes();
	var seconds = dt.getSeconds();
	var day = dt.getDay();
	var offset = dt.getTimezoneOffset();
	
	var pieces = new Array();
	var piece;
	for (var c=0; c < format.length; c++){
		if (format[c] == '\\'){
			c += 1;
			piece = format[c];
		} else {
			try {
				formatter = 'format_'+format[c]+'()';
				piece = eval(formatter);
			} catch (e){
				piece = format[c];
			}
		}
		pieces.push(piece);
	}
	return pieces.join('');
	
	function format_a(){
		if (hours > 11) return 'p.m.';
		return 'a.m.';
	}
	function format_A(){
		if (hours > 11) return 'PM';
		return 'AM';
	}
	function format_b(){
		return format_M().toLowerCase();
	}
	/* function format_B(){ // not implemented } */
	function format_d(){
		return ('' + date).zfill(2);
	}
	function format_D(){
		return format_l().slice(0, 3);
	}
	function format_f(){
		if (minutes == 0) return format_g();
		return format_g() + ':' + format_i();
	}
	function format_F(){
		var NAMES = ['January','February','March','April','May','June','July','August','September','October','November','December']
		return NAMES[month];
	}
	function format_g(){
		if (hours == 0) return '12';
		if (hours > 12) return ('' + (hours - 12));
		return ('' + hours);
	}
	function format_G(){
		return ('' + hours);
	}
	function format_h(){
		return format_g().zfill(2);
	}
	function format_H(){
		return format_G().zfill(2);
	}
	function format_i(){
		return ('' + minutes).zfill(2);
	}
	/* function format_I(){ // TODO: to be implemented } */
	function format_j(){
		return ('' + date);
	}
	function format_l(){
		var NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
		return NAMES[format_w()];
	}
	function format_L(mod){
		var y = (mod == undefined) ? year : year + mod
		return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)
	}
	function format_m(){
		return format_n().zfill(2);
	}
	function format_M(){
		return format_F().slice(0, 3);
	}
	function format_n(){
		return ('' + (month + 1));
	}
	function format_N(){
		var NAMES = ['Jan.','Feb.','March','April','May','June','July','Aug.','Sept.','Oct.','Nov.','Dec.']
		return NAMES[month];
	}
	function format_O(){
		var offset_hours = ('' +  parseInt(offset / 60)).zfill(2);
		var offset_minutes = ('' + (offset % 60)).zfill(2);
		var sign = (offset >= 0) ? '+' : '-';
		return (sign + offset_hours + offset_minutes)
	}
	function format_P(){
		if (minutes == 0 && hours == 0) return 'midnight';
		if (minutes == 0 && hours == 12) return 'noon';
		return format_f() + ' ' + format_a();
	}
	function format_r(){
		return dt.strfdate('D, j M Y H:i:s O');
	}
	function format_s(){
		return ('' + seconds).zfill(2);
	}
	function format_S(){
		if (date == 11 || date == 12 || date == 13) return 'th';
		var digit = date % 10;
		if (digit == 1) return 'st';
		if (digit == 2) return 'nd';
		if (digit == 3) return 'rd';
		return 'th';
	}
	function format_t(){
		var DAYS = [31, 28+format_L(), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
		return ('' + DAYS[month]);
	}
	/* function format_T(){ // TODO: to be implemented } */
	function format_U(){
		return '' + (Math.round(dt.getTime() / 1000) + (offset * 60))
	}
	function format_w(){
		return ('' + day);
	}
	function format_W(){
		var week_number;
		var jan1 = new Date();
		jan1.setDate(1);
		jan1.setMonth(0);
		jan1.setFullYear(year);
		var jan1_weekday = convertday(jan1.getDay()) + 1;
		var weekday = convertday(day) + 1;
		var day_of_year = parseInt(format_z());
		if (day_of_year <= (8 - jan1_weekday) && jan1_weekday > 4){
			if (jan1_weekday == 5 || (jan1_weekday == 6 && format_L(-1))){
				week_number = 53;
			} else {
				week_number = 52;
			}
		} else {
			if (format_L()){
				var i = 366;
			} else {
				var i = 365;
			}
			if ((i - day_of_year) < (4 - weekday)){
				week_number = 1;
			} else {
				var j = day_of_year + (7 - weekday) + (jan1_weekday - 1);
				week_number = parseInt(j / 7);
				if (jan1_weekday > 4){
					week_number -= 1;
				}
			}
		}
		return ('' + week_number);
		
		function convertday(d){
			return (7 + d - 1) % 7;
		}
	}
	function format_y(){
		return format_Y().slice(-2);
	}
	function format_Y(){
		return ('' + year);
	}
	function format_z(){
		var DAYS = [0, 31, 59+format_L(), 90, 120, 151, 181, 212, 243, 273, 304, 334]
		var result = DAYS[month] + date;
		return ('' + result);
	}
	function format_Z(){
		return '' + (offset * 60);
	}
}

More like this

  1. Django Collapsed Stacked Inlines by applecat 1 year, 10 months ago
  2. Django Collapsed Stacked Inlines by mkarajohn 3 years, 11 months ago
  3. Dynamically adding forms to a formset. OOP version. by halfnibble 9 years, 7 months ago
  4. Convert multiple select for m2m to multiple checkboxes in django admin form by abidibo 11 years, 8 months ago
  5. Django admin inline ordering - javascript only implementation by ojhilt 12 years ago

Comments

mawimawi (on March 6, 2007):

I think it would make much sense to also include a meaningful <noscript>blah</noscript> tag for browsers with disabled javascript.

#

mawimawi (on March 6, 2007):

ouch - did not recognize that html tags are being removed here... I meant [noscript]blah[/noscript]

#

robbie (on March 6, 2007):

Sorry mawimawi, but I don't follow your point. There's no actual "usage" code in this snippet; what are you suggesting should be noscript'd?

#

Please login first before commenting.