I’ve always hated doing simple date manipulation and having to create wacky variables like “millisecondsPerDay” where you multiply milliseconds by seconds by hours by whatever else. So here’s a useful (and largely untested) function, dateAdd(), which is similar to the function that ColdFusion-ers have enjoyed for years.
Full code (and instructions) after the jump.
In addition to my code being untested, I should point out that the datepart strings are different than those in ColdFusion. Where ColdFusion uses formats such as: “yyyy”, “q”, “m”, “y”, “d”, “w”, etc. I’ve cut corners and used the property names from the Date class (”fullYear”, “month”, “date”, “hours”, “minutes”, “seconds”, “milliseconds”) instead. This let me use:
returnDate[datepart] += number;
Which is basically a shorthand for something like:
returnDate["months"] += 3;
If you wanted to use the ColdFusion type notation it should be easy enough to extend the dateAdd() function and add another simple switch statement which converts the “yyyy” to “fullYear”, and so on.
Using the dateAdd() function is [hopefully] pretty straight forward.
- All three parameters are optional. If no parameters are passed, the current date is returned (similar to the Date class constructor).
- If only the first parameter (
datepart) is passed, the current date is returned. - If the first two parameters (
datepartandnumber) are passed, the function adds the specified number of date parts to the current date. For example, if you calleddateAdd("month", 3)the function would return the current date plus 3 months. If you calleddateAdd("month", -3)the function would return the current date minus 3 months. - If the first three parameters (
datepart,number, anddate) are passed, the function adds the specified number of date parts to the specified date. For example, if you calleddateAdd("day", 15, calendarStartDate)the function would return the value of thecalendarStartDatevariable (which must be a Date object) plus 15 days.
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/24/date-math-for-lazy-people/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white"
creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
private function init():void {
var zeroDate:Date = new Date(0);
/* fullYear */
arrColl.addItem({label:"+2 years", data:dateAdd("fullYear", 2, zeroDate)});
arrColl.addItem({label:"-2 years", data:dateAdd("fullYear", -2, zeroDate)});
/* month */
arrColl.addItem({label:"+11 months", data:dateAdd("month", 11)});
arrColl.addItem({label:"-11 months", data:dateAdd("month", -11)});
/* date */
arrColl.addItem({label:"+4 date", data:dateAdd("date", 4)});
arrColl.addItem({label:"-4 date", data:dateAdd("date", -4)});
/* hours */
arrColl.addItem({label:"+6 hours", data:dateAdd("hours", 6)});
arrColl.addItem({label:"-6 hours", data:dateAdd("hours", -6)});
/* minutes */
arrColl.addItem({label:"+45 minutes", data:dateAdd("minutes", 45)});
arrColl.addItem({label:"-45 minutes", data:dateAdd("minutes", -45)});
/* seconds */
arrColl.addItem({label:"+900 seconds", data:dateAdd("seconds", 900)});
arrColl.addItem({label:"-900 seconds", data:dateAdd("seconds", -900)});
/* milliseconds */
arrColl.addItem({label:"+720000 milliseconds", data:dateAdd("milliseconds", 720000)});
arrColl.addItem({label:"-720000 milliseconds", data:dateAdd("milliseconds", -720000)});
}
private function dateAdd(datepart:String = "", number:Number = 0, date:Date = null):Date {
if (date == null) {
/* Default to current date. */
date = new Date();
}
var returnDate:Date = new Date(date.time);;
switch (datepart.toLowerCase()) {
case "fullyear":
case "month":
case "date":
case "hours":
case "minutes":
case "seconds":
case "milliseconds":
returnDate[datepart] += number;
break;
default:
/* Unknown date part, do nothing. */
break;
}
return returnDate;
}
private function data_labelFunc(item:Object, column:DataGridColumn):String {
return dateFormatter.format(item[column.dataField]);
}
]]>
</mx:Script>
<mx:ArrayCollection id="arrColl" />
<mx:DateFormatter id="dateFormatter"
formatString="YYYY/MM/DD HH:NN:SS" />
<mx:Label text="Now: {dateAdd()}" />
<mx:DataGrid id="dataGrid"
dataProvider="{arrColl}"
sortableColumns="false"
width="400">
<mx:columns>
<mx:DataGridColumn dataField="label"
headerText="Label"
width="150" />
<mx:DataGridColumn dataField="data"
headerText="YYYY/MM/DD HH:NN:SS"
labelFunction="data_labelFunc" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
View source is enabled in the following example.
As a bonus tip… I believe you could do this with the Date constructor in ActionScript 2.0 as well, but I always find this handy. The following snippet creates a new Date object for January 45th, 2007. ActionScript cleverly adjusts that for you and returns the date of February 14th, 2007.
const JANUARY:uint = 0; // ... const DECEMBER:uint = 11; var d:Date = new Date(2007, JANUARY, 45); trace(d.toDateString()); // Wed Feb 14 2007
Although DO note that the Date.toDateString() method (as well as uint data type and const keyword) are specific to ActionScript 3.0.
Happy Flexing!



I think this should work for the various date aliases, bringing my
dateAdd()function a bit closer in line with ColdFusion’s (with the exception of support for “q” (quarter) and “ww” (week)):private function dateAdd(datepart:String = "", number:Number = 0, date:Date = null):Date { if (date == null) { /* Default to current date. */ date = new Date(); } var returnDate:Date = new Date(date.time); switch(datepart.toLocaleLowerCase()) { case "yyyy": case "year": datepart = "fullYear"; break; case "m": datepart = "month"; break; case "y": case "d": case "w": case "day": datepart = "date"; break; case "h": datepart = "hours"; break; case "n": datepart = "minutes"; break; case "s": datepart = "seconds"; break; case "l": datepart = "milliseconds"; break; } switch (datepart.toLowerCase()) { case "fullyear": case "month": case "date": case "hours": case "minutes": case "seconds": case "milliseconds": returnDate[datepart] = number; break; default: /* Unknown date part, do nothing. */ break; } return returnDate; }“fullyear” does not work. It’s actualy “fullYear” with the capital Y.
To fix this remove the “.toLowerCase()” and pass in correct case. change the
line-> case “fullyear”:
to-> case “fullYear”:
Thanks for the example. I find this site more helpful than the Adobe site for finding the exact tweek you need.
Keep up the great work.
Thanks dude. you made my day.
Thanks for the info bro…i was searching for this for a long time…u’re certainly pro at this…
A optimize version of the code.
Note: I do not use a ColdFusion Server. Modify it has your require for that.
public static function dateAdd(datepart:String = "", number:Number = 0, date:Date = null):Date { date = date == null ? new Date() : new Date(date.time); switch(datepart.toLocaleLowerCase()) { case "y": case "fullyear": case "yyyy": case "year": datepart = "fullYear"; break; case "m": case "month": datepart = "month"; break; case "d": case "day": case "date": datepart = "date"; break; case "h": case "hours": datepart = "hours"; break; case "minutes": case "n": datepart = "minutes"; break; case "seconds": case "s": datepart = "seconds"; break; case "milliseconds": case "l": datepart = "milliseconds"; break; default: datepart = null; } if(datepart != null) date[datepart] += number; return date; }I hate to gush, but this is terrific. Now a part of my utilities from now until forever!
Vesta,
That’s OK, gush away.
Peter
To add a week support, you can modify your script, and add this lines:
switch(datepart.toLocaleLowerCase()) { ... case "week": datepart = "date"; number = number * 7; break; ... }I notice that it gets a little goofy calculating month adds when the current month is longer than the target month. For instance:
dateAdd(”m”,1,’1/31/2009′) ends up as 3/2/2009
Any thoughts on a workaround there? I ended up writing my own like this:
date = new Date(date[”fullYear”]+Math.floor((date[”month”]+number)/12),(date[”month”]+number)%12,date[”date”]);
However, I am a Flex noob and figured that you might have a more glamorous approach. :)
crap… I just realized I posted an earlier iteration of that solution. On the one I ended up going with I determined whether or not the max days in month of the target month was less than date[”date”], and if so, I would use that value instead of date[”date”] like you see above.
You are awesome…I always find everything here i want in flex….please dont stop this as you are helping many students like me…
Great function! Thanks so much for posting this!