text: define(["../_base/lang", "../_base/array"], function(lang, array) {
  	// module:
  	//		dojo/date/stamp
  	// summary:
  	//		TODOC
  
  var stamp = lang.getObject("dojo.date.stamp", true);
  
  /*=====
  dojo.stamp = {
  	// summary:
  	//		TODOC
  };
  stamp = dojo.stamp;
  =====*/
  
  // Methods to convert dates to or from a wire (string) format using well-known conventions
  
  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.
  	//		Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
  	//		The following combinations are valid:
  	//
  	//			* dates only
  	//			|	* yyyy
  	//			|	* yyyy-MM
  	//			|	* yyyy-MM-dd
  	// 			* times only, with an optional time zone appended
  	//			|	* THH:mm
  	//			|	* THH:mm:ss
  	//			|	* THH:mm:ss.SSS
  	// 			* and "datetimes" which could be any combination of the above
  	//
  	//		timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
  	//		Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
  	//		input may return null.  Arguments which are out of bounds will be handled
  	// 		by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
  	//		Only years between 100 and 9999 are supported.
  	//
    	//	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.
  	//		Uses 1970-01-01T00:00:00.0Z by default.
  
  	if(!stamp._isoRegExp){
  		stamp._isoRegExp =
  //TODO: could be more restrictive and check for 00-59, etc.
  			/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
  	}
  
  	var match = stamp._isoRegExp.exec(formattedString),
  		result = null;
  
  	if(match){
  		match.shift();
  		if(match[1]){match[1]--;} // Javascript Date months are 0-based
  		if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
  
  		if(defaultTime){
  			// mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
  			defaultTime = new Date(defaultTime);
  			array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
  				return defaultTime["get" + prop]();
  			}), function(value, index){
  				match[index] = match[index] || value;
  			});
  		}
  		result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults
  		if(match[0] < 100){
  			result.setFullYear(match[0] || 1970);
  		}
  
  		var offset = 0,
  			zoneSign = match[7] && match[7].charAt(0);
  		if(zoneSign != 'Z'){
  			offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
  			if(zoneSign != '-'){ offset *= -1; }
  		}
  		if(zoneSign){
  			offset -= result.getTimezoneOffset();
  		}
  		if(offset){
  			result.setTime(result.getTime() + offset * 60000);
  		}
  	}
  
  	return result; // Date or null
  };
  
  /*=====
  	dojo.date.stamp.__Options = function(){
  		//	selector: String
  		//		"date" or "time" for partial formatting of the Date object.
  		//		Both date and time will be formatted by default.
  		//	zulu: Boolean
  		//		if true, UTC/GMT is used for a timezone
  		//	milliseconds: Boolean
  		//		if true, output milliseconds
  		this.selector = selector;
  		this.zulu = zulu;
  		this.milliseconds = milliseconds;
  	}
  =====*/
  
  stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
  	//	summary:
  	//		Format a Date object as a string according a subset of the ISO-8601 standard
  	//
  	//	description:
  	//		When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
  	//		The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
  	//		Does not check bounds.  Only years between 100 and 9999 are supported.
  	//
  	//	dateObject:
  	//		A Date object
  
  	var _ = function(n){ return (n < 10) ? "0" + n : n; };
  	options = options || {};
  	var formattedDate = [],
  		getter = options.zulu ? "getUTC" : "get",
  		date = "";
  	if(options.selector != "time"){
  		var year = dateObject[getter+"FullYear"]();
  		date = ["0000".substr((year+"").length)+year, _(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 < 100 ? "0" : "") + _(millis);
  		}
  		if(options.zulu){
  			time += "Z";
  		}else if(options.selector != "time"){
  			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
  };
  
  return stamp;
  });
  