Ultrashock Tutorials > Flash5 > The Actionscript Date Object  
 
By: John Dalziel


Source File

 

 
The Actionscript Date Object
 

 

What time is it? It's a simple enough question, but the answer is more complex than you might think. This tutorial serves as an introduction to the Flash 5 Actionscript Date object. It also contains some important information concerning the problem with daylight saving time. It is aimed at Flash users who are already proficient with Actionscript.

The Date object

The Actionscript Date object is a convenient way of storing a large collection of related variables as a single package. Each instance of a Date object contains both time elements (hours, minutes, seconds, milliseconds) and calendar elements (days, months, years). When you create a new instance of the Date object, you are capturing a snapshot of time and calendar values of the current time.

To create an instance of the Date object we use the syntax:

now = new Date()

This creates an instance of the Date object called 'now'. All the methods of the Date object are then called from this instance. For example:

Hours = now.getHours()

sets a variable 'Hours' to equal the number of hours stored in the Date object 'now'.


"Real time"

A date object has a static value. It is not a pointer to the current time. If you wait ten minutes and check the object again it will not have moved on.
If you want to create a 'real time' clock then you need to update your Date object every frame. The simplest way to do this is with the onClipEvent method of the Movie object.
Create a new movie object and add the following code to an instance of the movie.

onClipEvent (enterFrame) {
    now = new Date()
    now_display = now.toString()
}

If you add a dynamic text box (displaying the variable 'now_display') inside this movie you'll find you have a clock that updates in real time. It may not be very pretty but it doesn't get any simpler. This principle forms the basis of any clock simulation you will ever build. With a bit of playing around you should be able to use these and other values to produce all manner of clock and calendar displays.


Local time

If you ask two people in different longitudes, "What time is it?" you'll get two different answers. For example, when it is 11 AM in New York, it is 4 PM in London and 1 AM the following day in Tokyo.

This is because the Earth is divided longitudinally (pole to pole) into 24 time zones spaced 15° apart. The lines dividing the time zones are not all straight but the areas within each time zone observe a local or 'civil time' one hour earlier than the zone immediately to the east. Other factors such as Daylight Saving time (see later) may also affect the value of local time. Consequently the same moment in time has a unique local interpretation depending on the time of year and your position on Earth.

For the purposes of Actionscript, local time is the time returned by the operating system on which the Flash Player is running. We use the following methods to get local time values:

now_Milliseconds = now.getMilliseconds()
returns the number of Milliseconds as an integer between 0 - 999

now_Seconds = now.getSeconds()
returns the number of Seconds as an integer between 0 - 59

now_Minutes = now.getMinutes()
returns the number of Minutes as an integer between 0 - 59

now_Hours = now.getHours()
returns the number of Hours as an integer between 0 - 23

now_Day = now.getDay()
returns the day of the week as an integer between 0 - 6
(0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday,
4 = Thursday, 5 = Friday, 6 = Saturday)

now_Date = now.getDate()
returns the day of the month as an integer between 1 - 31

now_Month = now.getMonth()
returns the number of Months as an integer between 0 - 11
(0 = January, 1 = February, 2 = March, 11 = December)

now_FullYear = now.getFullYear()
returns the number of Years as a 4 digit integer


A shorthand value of the year is also available through .getYear but this method is probably best avoided.

now_Year = now.getYear()
returns the number of Years since 1900 as an integer
(e.g. 0 = year 1900, 1 = year 1901, 2 = year 1902, 100 = year 2000)

Actionscript is based upon ECMA-262, the same standard used by Javascript. Consequently the Actionscript and Javascript Date objects and methods are almost identical. The .getyear method is a throwback to earlier incarnations of the Javascript Date object that existed before the introduction of .getFullYear. There is no UTC equivalent to .getyear .

Universal Coordinated Time (UTC)

If you've ever built a website that relies on the correct time (any e-commerce site for example) then you'll understand the clear need for a coordinated world-wide standard of time. The history behind this achievement is a long and fascinating story but sadly out with the realms of this tutorial. If you would like to know more I would strongly advise you to read, 'The Calendar' by David Ewing Duncan (ISBN 1-85702-979-8).

Suffice to say, these days we have a Universal Coordinated Time (sometimes called 'Zulu' time but usually shortened to UTC). This is the modern equivalent of Greenwich Mean Time (GMT) and more or less equates to the same thing: It is the local unadjusted time at a single longitude on the planet: the prime meridian. When it is 4PM UTC in New York, it is 4 PM UTC in London and 4 PM UTC in Tokyo.

It is often useful to know the difference between the current local time and the current UTC time. The following method returns the difference, measured in minutes.

now_TimezoneOffset = now.getTimezoneOffset()
returns the number of minutes as an integer
Be warned though, the term 'TimezoneOffset' is a bit of a red
herring as this value also includes any offset for Daylight Saving Time.
More about this later.

We use the following methods to get Universal Standard Time values:

now_UTCMilliseconds = now.getUTCMilliseconds()
returns the number of Milliseconds as an integer between 0 - 999

now_UTCSeconds = now.getUTCSeconds()
returns the number of Seconds as an integer between 0 - 59

now_UTCMinutes = now.getUTCMinutes()
returns the number of Minutes as an integer between 0 - 59

now_UTCHours = now.getUTCHours()
returns the number of Hours as an integer between 0 - 23

now_UTCDay = now.getUTCDay()
returns the day of the week as an integer between 0 - 6
(0 = Sunday, 1 = Monday, 2 = Tuesday, 3 = Wednesday, 4 = Thursday,
5 = Friday, 6 = Saturday)

now_UTCDate = now.getUTCDate()
returns the day of the month as an integer between 1 - 31

now_UTCMonth = now.getUTCMonth()
returns the number of Months as an integer between 0 - 11
(0 = January, 1 = February, 2 = March, 11 = December)

now_UTCFullYear = now.getUTCFullYear()
returns the number of Years as a 4 digit integer

The Flash player measures UTC time in a similar way to Javascript. It maintains a counter that tracks the number of milliseconds that have elapsed since midnight on January 1, 1970. Dates prior to this will return a negative number.

This value can be tracked using the .getTime method.

now_Time = now.getTime()
returns the number of milliseconds since midnight Jan 1st 1970 as an
integer

Thankfully the Flash player does not suffer from the old 32 bit Unix Date problem (Unix overflows after February 2106) and quite happily records dates up into the 33rd millennium.


Daylight Saving Time

Thanks mainly to the efforts of a London builder named William Willett we have the controversial notion of daylight saving time (DST). This practice means that in some locations, all clocks are put one hour ahead of UTC time during the summer months.

In a perfect world daylight saving time wouldn't be an issue. You would think that, as local times are determined from the operating system and, as the OS adjusts automatically for DST, then it would always be correct. In reality though Flash calculates 'local' time rather than reads it. This would be fine if it was calculated correctly but due to the unfortunate assumption that dates for DST are a global standard we have a problem.

Flash follows the US convention for DST:

DST begins at 2am on the first Sunday of April.
DST ends at 2am on the last Sunday of October

The rest of the world (and in fact some parts of the US) use there own dates for DST. In the European Union for example DST has now been standardized to begin at 1am on the last Sunday of March and end at 1am on the last Sunday of October.

So what does this mean?

Well, if you use local time on your site (in a real time clock for example) and your site is viewed by someone out with the US, then at certain times of year the time on your clock will be out by an hour. In the case of Europe, between the last Sunday in March and the first Sunday in April the local time on your machine will be one hour ahead of Flash local time.

It's official

Macromedia have recently acknowledged this issue as a bug. They are currently investigating ways to address the problem in a future release of the player. It is worth noting as well that an earlier issue to do with the .getHour method may well have the same root cause. Macromedia claim however that this issue has already been corrected.

What can you do?

Honestly, not a lot. If you are using dates and timestamps for internal use then always use UTC. UTC time is constant and is not unadjusted for time zones and DST. This is the only reliable time available to you. If you want to use local time then you'll have to live with the fact that it'll be out by an hour (out with the US) at certain times of the year.

In the next tutorial I'll look at ways of extending the functionality of the Date object. In theory it should be possible to code some form of lookup table vs location to do some local correction but in reality though the politics of DST are a very muddy affair.

To give you some idea, Cuba always starts on April 1st (as does Syria and Iraq). China used to adopt DST but doesn't any more. Israel has a set number of DST days mandated in law but makes the starting dates up every year. Saskatchewn province doesn't but the rest of Canada does. In the US, DST is not observed in the Eastern Time Zone portion of the State of Indiana, or in the state of Arizona except for the Navajo Indian Reservation, which does observe DST! In short, it's a mess and we're stuck with it.

Another possible solution involves using the Javascript Date object to validate the local times generated by the Flash player. I've written a tool to compare both objects if you want to look at the differences (click on TimeMachines 1 from the top menu). It should be pointed out though that Javascript Date object is subject to a number of issues itself so this is by no means a rock solid solution.


Setting dates

One of the most common uses for the Date object is to store specific dates. To do this we use the extended Date syntax:

Date(year, month, date, hour, minute, second, millisecond )

Dates can be set relative to local time or UTC time. If specific dates are to be compared then it would be wise to use the slightly more verbose UTC syntax. This allows for comparisons irrespective of local modifiers such as time zones and DST.

This example demonstrates the difference in the values of .getTime when the same date is set in local and UST time. This difference is the result of DST being in effect.

local = new Date(2001, 5, 1, 0, 0, 0, 0 ) local.getTime()
produces the value 988731000000

UTCTest = new Date(Date.UTC(2001 ,5 ,1 ,0 ,0 ,0 ,0)) UTCTest.getTime()
produces the value 988734600000


We can use the following methods to alter specific time values. Replace new_value with a value of your choice.

now.setMilliseconds(new_value)
changes the number of Milliseconds to a new value
(integer between 0 - 999)

now.setSeconds(new_value)
changes the number of Seconds to a new value
(integer between 0 - 59)

now.setMinutes(new_value)
changes the number of Minutes to a new value
(integer between 0 - 59)

now.setHours(new_value)
changes the number of Hours to a new value
(integer between 0 - 23)

now.setDate(new_value)
changes the day of the month to a new value
(integer between 1 - 31)

now.setMonth(new_value)
changes the number of Months to a new value
(integer between 0 - 11)
(0 = January, 1 = February, 2 = March, 11 = December)

now.setFullYear(new_value)
changes the number of Years to a new value (4 digit integer)

And a couple of whacky ones…

now.setYear(new_value)
changes the number of Years since 1900 (integer)
(e.g. 0 = year 1900, 1 = year 1901, 2 = year 1902, 100 = year 2000))

now.setTime(new_value)
changes the number of milliseconds since midnight Jan 1st 1970 (integer)


And then there are their UTC equivalents. Replace new_value with a value of your choice.

now.setUTCMilliseconds(new_value)
changes the number of Milliseconds to a new value
(integer between 0 - 999)

now.setUTCSeconds(new_value)
changes the number of Seconds to a new value
(integer between 0 - 59)

now.setUTCMinutes(new_value)
changes the number of Minutes to a new value
(integer between 0 - 59)

now.setUTCHours(new_value)
changes the number of Hours to a new value
(integer between 0 - 23)

now.setUTCDate(new_value)
changes the day of the month to a new value
(integer between 1 - 31)

now.setUTCMonth(new_value)
changes the number of Months to a new value
(integer between 0 - 11)
(0 = January, 1 = February, 2 = March, 11 = December)

now.setUTCFullYear(new_value)
changes the number of Years to a new value (4 digit integer)


Comparing dates

A common misconception with the Date object is that comparisons are black art. Prepare to be astounded. The beauty of the object is that you can simply add them and subtract them from each other. For example, here's how to find out how many shopping days to Christmas!

now = new Date()
xmas = new Date(2001, 11, 25, 0, 0, 0, 0 )
howlong = xmas-now


Extending the Actionscript Date Object

There are a number of useful date functions that are not immediately available to us. By using the .prototype method we can extend the basic functionality of the date object to include new methods that return the names of the days and months, check for leap years and perform date comparisons.

Like any other function it must be declared before it can be called so make sure you include all the extensions you wish to use early in your movie.


// Prototype function to return the weekday name
Date.prototype.getDayName = function () {
    var daynames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')
    return daynames[this.getUTCDay()]
}


// Prototype function to return the month name
Date.prototype.getMonthName = function () {
    var monthnames = monthnames = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
    return monthnames[this.getUTCMonth()]
}


// Prototype function to return if a date is a leap year or not
Date.prototype.leapYear = function () {
    var Year = this.getUTCFullYear()
    if (((Year % 4)==0) && ((Year % 100)!=0) || ((Year % 400)==0)){return (true)}else{return (false)}
}


// Prototype function to return the number of days in the current month
Date.prototype.getDaysInMonth = function () {
    var daysinmonth = new Array(31,28,31,30,31,30,31,31,30,31,30,31)
    if (this.leapyear() == true) {daysinmonth[1] = 29}
    return daysinmonth[this.getUTCMonth()]
}

// Prototype to return AM or PM
Date.prototype.getAMPM = function () {
    var Hour = this.getUTCHours()
    if (Hour > 12) {return ("PM")} else {return ("AM")}
}

// Prototype to convert 24 hour to 12 hour clock (integer 0-11)
Date.prototype.getHour12 = function () {
    var Hour = this.getUTCHours()
    if (Hour > 12) {return (Hour-12)} else {return (Hour)}
}


// Prototype to return the difference between two dates in milliseconds
Date.prototype.getMillisecondsBetween = function (then) {
    var Time1 = this.getTime()
    var Time2 = then.getTime()
    var Time3 = Time2-Time1
    if (Time3 < 0) {Time3 = (Time3 * -1)}
    return (Time3)
}

Epilogue

The correct time is the single most important variable in any dynamic site. Hopefully this tutorial has helped to demystify one of the most useful new objects in the Actionscripters armoury.

 

 
©2001 Ultrashock.com Inc. - All rights reserved