Home > Flex, FlexDateUtils, code, library > Flex Date Utils – Date and Time Format (Part I)

Flex Date Utils – Date and Time Format (Part I)

December 12th, 2008 Gareth Leave a comment Go to comments

I will have to split this post into 2 separate parts, as there are several methods that are all related, and this post would be huge. In this post I will go over what is happening behind the scenes when date, time, and dateTimeFormat are called. All of these methods are private, so other than explaining how and why they work, nothing will be accessible outside of the DateUtils class.

// Internal variable used in date/time formatting
private static var _dateFormatter:DateFormatter;
private static function get dateFormatter():DateFormatter {
	if ( !_dateFormatter ) {
		_dateFormatter = new DateFormatter;
	}
	return _dateFormatter;
}

I use a static getter for a DateFormatter instantiation so that I can use the built in features of the DateFormatter class to format my dates. I figure, why reinvent the wheel, when it has been done so well in Flex already :)

/**
 * @private
 * 
 * Calculates a timeZoneOffset, and converts it to a string, in standard GMT XX:XX format
 * 
 * @param date	The date on which to calculate the offset
 * 
 * @return		The formatted time zone designation
 */
private static function buildTimeZoneDesignation( date:Date ):String {
	if ( !date ) {
		return "";
	}
	var timeZoneAsString:String = "GMT ";
	// timezoneoffset is the number that needs to be added to the local time to get to GMT, so
	// a positive number would actually be GMT -X hours
	if ( date.getTimezoneOffset() / 60 > 0 && date.getTimezoneOffset() / 60 < 10 ) {
		timeZoneAsString += "-0" + ( date.getTimezoneOffset() / 60 ).toString();
	} else if ( date.getTimezoneOffset() < 0 && date.timezoneOffset / 60 > -10 ) {
		timeZoneAsString += "0" + ( -1 * date.getTimezoneOffset() / 60 ).toString();
	}
	// add zeros to match standard format
	timeZoneAsString += "00";
	return timeZoneAsString;
}

As the description states, this method takes a date and builds the time zone designation in the GMT -XX:00 timezone offset. If date is null, then it returns an empty string.

/**
 * @private
 * 
 * This function will remove any invalid characters from the date/time mask based upon a pattern
 * 
 * @param mask			The string for matching
 * @param pattern		The valid characters for this mask
 * @param defaultValue	The default value to return to the calling page should the mask not match the pattern
 * 
 * @return				Returns a validated <code>mask</code> based upon the original pattern
 */
private static function removeInvalidDateTimeCharacters( mask:String, pattern:String, defaultValue:String ):String {
	// test for invalid date and time characters
	if ( mask.replace( new RegExp( pattern, "ig" ), "" ).length > 0 ) {
		// if user is passing an invalid mask, default to defaultValue
		mask = defaultValue;
	}
	// temporarily replace TZD with lowercase tzd for replacing later
	return mask.replace( new RegExp( "TZD", "i" ), "tzd" );
}

I use this method to remove any bad characters that may have been passed in to the date/time formatters. It takes a mask, a pattern, and a default value. The default value is my fallback in case an invalid characters have been passed in. First I replace all characters based upon the pattern passed to the method. If any characters are left, then it is a bad pattern, and it uses the default value. I then replace TZD and switch it to lowercase so that it can be replaced with the actual time zone designation at a later point (and the dateformatter does not balk at it when it comes across it).

/**
 * @private
 * 
 * Formats a date into a certain date/time format
 * 
 * @param date			The date to format
 * @param mask			The string for matching
 * @param pattern		The valid characters for this mask
 * @param defaultValue	The default value to return to the calling page should the mask not match the pattern
 * 
 * @return		A formatted date
 */
private static function buildDateTime( date:Date, mask:String, pattern:String, defaultValue:String ):String {
	dateFormatter.formatString = removeInvalidDateTimeCharacters( mask, pattern, defaultValue );
 
	return dateFormatter.format( date ).replace( new RegExp( "TZD", "i" ), buildTimeZoneDesignation( date ) );
}

This is where the dateformat “magic” happens :) The function receives a date, the mask of how to format the date, a pattern that determines which characters are valid characters, and a default value to use should there be any invalid characters.

This sets the formatString of the static dateFormatter and removes any invalid characters. Then it formats the date based upon that formatString, and finally replaces any TZD it finds (which would have been lowercased in the removeInvalidDateTimeCharacters method) with the actual timezone designation, if there was a time zone designation requested in the mask.

Even though none of these methods are available outside of the DateUtils class, I always like to know how things are working under the hood, and hopefully others do too.

All methods in this series are describing code in the FlexDateUtils package I put on Google code.