Localising Date Time display in ASP.NET and Javascript

Display localised time on your webpages.
December 02 2011

 

One of the tickets I worked on this week was to add a “date last updated” to some stock market data being displayed.  I needed to display “As of [last update date] (30min delay)” underneath the market data table.

Local1

The data is retrieved from an xml feed that contains the last updated time in the format “HH:mm dd/MM/yyyy”.  The time used is local to Sydney Australia, “AUS Eastern Standard Time”, 10 hours ahead of GMT and +11 in Summer.  I wanted to ensure the last updated date was not in the future for people viewing from a different time zone; Brisbane for example, which is also +10 GMT but doesn’t have daylight savings.

The way I did this was to send the UTC time back to the client browser and use javascript to convert that to the local time zone of the client.  I also wanted a fail safe and included the Sydney time as default.  I created a server-side property on my ascx to convert the time I recieved in my stock data feed into GMT:

protected DateTime? LastUpdatedDateGmt
{
    get
    {
        if (!LastUpdatedDate.HasValue) return null;

        // Time comes in as Sydney time.
        TimeZoneInfo sydneyTimeZone = TimeZoneInfo.GetSystemTimeZones().First(p => p.StandardName == "AUS Eastern Standard Time");
        return TimeZoneInfo.ConvertTimeToUtc(LastUpdatedDate.Value, sydneyTimeZone);                        
    }
}

The TimeZoneInfo class's GetSystemTimeZones provides an enumeration of all timezones and are Daylight Savings aware.  I use the Sydney time zone of "AUS Eastern Standard Time" to convert from and into Utc (GMT 0) time.  The html I sent back to the browser looks like the following:

<div class="refreshtime">            
    As of <span id='time' class='time' utctime='Thu Dec 01 2011 22:54:00'>2011-12-02 9:54:00</span> (30min delay)
</div>
<script type=”text/javascript”>MarketData.ConvertStockLastUpdatedToLocalTime();</script>

 

With the above, at a minimum a site visitor in my time zone will see last updated time 1 hour or so in the future.  Not bad, but could be better.  Next I use some javascript to find the span element containing the utctime attribute and extract the utc time of the last update.  I can then convert this to the browsers local time zone.

var MarketData = {    
    ConvertStockLastUpdatedToLocalTime: function() {
        var timeElements = getElementsByAttribute(document, '*', 'utctime');
        if (timeElements != 'undefined' && timeElements) {
            var oAttribute;
            var oCurrent;
            for (var i = 0; i < timeElements.length; i++) {
                oCurrent = timeElements[i];
                oAttribute = oCurrent.getAttribute && oCurrent.getAttribute('utctime');

                var d = new Date();
                var utcTime = new Date(oAttribute);
                var localTime = new Date(utcTime + ‘ GMT’);
                var localTimeString = localTime.getFullYear() + '-' + pad(localTime.getMonth() + 1, 2) + '-' + pad(localTime.getDate(), 2) + ' ' + pad(localTime.getHours(), 2) + ':' + pad(localTime.getMinutes(), 2) + ':' + pad(localTime.getSeconds(), 2);

                timeElements[i].innerHTML = localTimeString;
            }
        }              
    }
};

The above finds all the elements in the page with the utctime attribute and extracts that value for conversion.  Once extracted I just need to assign it a timezone and let the Data function take care of the conversion to local time for me.  I converted for the format “yyyy-MM-dd HH:mm:ss” format by using the custom Pad function.

function getElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue) {
    var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    var oAttributeValue = (typeof strAttributeValue != "undefined") ? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)", "i") : null;
    var oCurrent;
    var oAttribute;
    for (var i = 0; i < arrElements.length; i++) {
        oCurrent = arrElements[i];
        oAttribute = oCurrent.getAttribute && oCurrent.getAttribute(strAttributeName);
        if (typeof oAttribute == "string" && oAttribute.length > 0) {
            if (typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))) {
                arrReturnElements.push(oCurrent);
            }
        }
    }
    return arrReturnElements;
}

function pad(number, length) {

    var str = '' + number;
    while (str.length < length) {
        str = '0' + str;
    }

    return str;
}

Post a comment

comments powered by Disqus