[dojo-contributors] #3007: dojo.date.stamp refactor

Adam L. Peller adam at peller.org
Fri Jun 1 14:01:24 EDT 2007


I'm trying to simplify the date serialization code, in the spirit of
0.9.  The full iso8601 spec doesn't seem to be justified here (though
I guess we could do it in dojox?  doing iso8601, as James Overton
points out in #2480)  We had originally had code for both "rfc3339"
and "iso8601"  Upon further reading of the specs, we're really not
faithful to either -- rfc3339 seems to require both date and time all
the time, and I sort of understand why.  All the optional stuff gets
tricky.  I wasn't able to find great specs for the new ECMAScript or
anything else I liked, so I made up what I thought was a reasonable
compromise -- an rfc3339 like subset with optional date and time
pieces, and an optional timezone.  That seems to cover most of our
uses right now.

The millisecond and zulu stuff is nice for completeness, but I'm sure
we could argue those are choices we shouldn't be offering.  I dropped
the compact form (20070601)

I don't know offhand if it's faster to do a regexp with matching or a
few splits -- I'd guess the latter, but I'll confirm before I check
this in.

Thoughts?

-Adam

dojo.provide("dojo.date.stamp");

// Methods to convert dates to or from a wire (string) format using
well-known conventions

dojo.date.stamp.fromISOString = function(/*String*/formattedString,
/*Number*/defaultTime){
	//	summary:
	//		Returns a Date object given a string formatted according to a
subset of the ISO-8601 standard
	//
	//	description:
	//		Accepts a string formatted according to a profile of ISO8601 as defined by
	//		RFC3339 (http://www.ietf.org/rfc/rfc3339.txt), except that
partial input is allowed.
	//		The following combinations are valid:
	//			yyyy-MM-dd
	//			THH:mm:ss
	//			THH:mm:ss
	//			yyyy-MM-ddTHH:mm:ss
	//			THH:mm:ssTZD
	//			yyyy-MM-ddTHH:mm:ssTZD
	//		where TZD is Z or +/- followed by a time expression HH:mm
	//		Assumes the local time zone if not specified.  Returns null if invalid?
	//
  	//	formattedString:
	//		A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
	//
	//	defaultTime:
	//		Used for defaults for fields omitted in the formattedString.  If omitted,
	//		uses 1970-01-01T00:00:00.0Z for default.

	var result = new Date(defaultTime || 0);
//PERF: is it faster to do this in a regexp?
	var segments = formattedString.split("T");
	if(segments[0]){
		var dateSegments = segments[0].split("-");
		result.setFullYear(dateSegments[0]);
		result.setMonth(0); // need to do this so the date doesn't wrap
around; reconsider defaultTime arg?
		result.setDate(dateSegments[2]);
		result.setMonth(dateSegments[1]-1);
	}
	if(segments[1]){
		var timeSegments = segments[1].substring(0, 8).split(":");
		result.setHours(timeSegments[0]);
		result.setMinutes(timeSegments[1]);
		result.setSeconds(timeSegments[2]);
		var remainder = segments[1].substring(8);
		if(remainder[0] === "."){
			//TODO: millis?
		}
		if(remainder){
			var offset = 0;
			if(remainder[0] != 'Z'){
				var gmtOffset = remainder.substring(1).split(":");
				offset = (gmtOffset[0] * 60) + (Number(gmtOffset[1]) || 0);
				if(remainder[0] != '-'){ offset *= -1; }
			}
			offset -= result.getTimezoneOffset();
			if(offset){
				result.setTime(result.getTime() + offset * 60000);
			}
		}
	}

	return result;
}

dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*Object*/options){
	//	summary:
	//		Format a Date object as a string according a subset of the
ISO-8601 standard
	//
	//	description:
	//		Times are formatted using the local time zone.  Does not check bounds.
	//		Invalid dates such as March 32 will be handled the according to
the Date() constructor.
	//
	//	dateObject:
	//		A Date object
	//
	//	object {selector: string, zulu: boolean}
	//		selector- "date" or "time" to format selected portions of the Date object.
	//			Both date and time will be formatted by default.
	//		zulu- if true, UTC/GMT is used for a timezone

	var _ = function(n){ return (n < 10) ? "0"+n : n; }
	options = options || {};
	var formattedDate = [];
	var getter = options.zulu ? "getUTC" : "get";
	var date = "";
	if(options.selector != "time"){
		date = [dateObject[getter+"FullYear"](),
_(dateObject[getter+"Month"]()+1),
_(dateObject[getter+"Date"]())].join('-');
	}
	formattedDate.push(date);
	if(options.selector != "date"){
		var time = [_(dateObject[getter+"Hours"]()),
_(dateObject[getter+"Minutes"]()),
_(dateObject[getter+"Seconds"]())].join(':');
//		var millis = dateObject[getter+"Milliseconds"]();
//		if(options.milliseconds){
//			time += "."+millis;
//		}
		if(options.zulu){
			time += "Z";
		}else{
			var timezoneOffset = dateObject.getTimezoneOffset();
			var absOffset = Math.abs(timezoneOffset);
			time += (timezoneOffset > 0 ? "-" : "+") +
				_(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
		}
		formattedDate.push(time);
	}
	return formattedDate.join('T'); // String
}



More information about the dojo-contributors mailing list