tags:

views:

311

answers:

6

I'm a Java developer and I'm used to the SimpleDateFormat class that allows me to format any date to any format by settings a timezone.

Date date = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");

sdf.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
System.out.println(sdf.format(date)); // Prints date in Los Angeles

sdf.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
System.out.println(sdf.format(date)); // Prints same date in Chicago

SimpleDateFormat is a pretty neat solution in Java but unfortunately I can't find any similar alternative in Javascript.

I'm extending the Date prototype in Javascript to do exactly the same. I have dates in Unix format but I want to format them in different timezones.

Date.prototype.format = function(format, timezone) {
    // Now what?
    return formattedDate;
}

I'm looking for a neat way to do this rather than a hack.

Thanks

A: 

Don't write your own stuff; just get datejs: http://www.datejs.com/

You can figure out what the timezone offset is set to in the execution environment like this:

var local = new Date();
var utc = Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds());
var tz = (utc - local.getTime()) / (60 * 60 * 1000);
Pointy
The goal is to handle timezones, DateJS doesn't seem to do so.
Elie
A: 

If you're just passing the raw TZ there's nothing really complicated about adjusting the hours. My example below is of course abbreviated. Yours may get quite long depending on how many patterns you'd handle.

Date.prototype.format = function(format, tzAdjust) {
    // adjust timezone
    this.setHours(this.getHours()+tzAdjust)
    // pad zero helper - return "09" or "12"
    var two = function(s){ return s+"".length==1 ? "0"+s : s+""; }
    // replace patterns with date numbers
    return format.replace(/dd|MM|yyyy|hh|mm|ss/g, function(pattern){
        switch(pattern){
            case "d" : return this.getDate();
            case "dd" : return two(this.getDate());
        }
    });
}
mwilcox
This is not a very clean solution. Because let's say you want to format the same date twice, it will be adjusted twice.On the other hand, getHours returns the hour on the user's timezone, adding the raw offset is not enough, you need to consider the user's timezone as well (getTimezoneOffset()).Anyway, by using setHours, you'll be changing the date which is a wrong way to handle dates.
Elie
A: 

Attempting to (ever so slightly) improve upon mwilcox's suggestion:

Date.prototype.format = function(format, tzAdjust) {

    // get/setup a per-date-instance tzDate object store
    var tzCache = this.__tzCache = this.__tzCache || (this.__tzCache = {});

    // fetch pre-defined date from cache 
    var tzDate = tzCache[tzAdjust];
    if ( !tzDate )
    {
      // on miss - then create a new tzDate and cache it
      tzDate = tzCache[tzAdjust] = new Date( this );
      // adjust by tzAdjust (assuming it's in minutes 
      // to handle those weird half-hour TZs :) 
      tzDate.setUTCMinutes( tzDate.getUTCMinutes()+tzAdjust );
    }

    return format.replace(/dd|MM|yyyy|hh|mm|ss/g, function(pattern){
               // replace each format tokens with a value 
               // based on tzDate's corresponding UTC property
             });
}
Már Örlygsson
A: 

You are clearly asking two questions in one, formatting and time zone. They need to be addressed separately. Formatting is pretty trivial, if none of the other answers will do for that you will have to be more specific.

As for the time and time zone, if you have your server inject the UTC time, preferably as UNIX time in milliseconds, into the JavaScript, you can compare that to the time on the client machine, and thus work out how far from UTC the client is. Then you can calculate the time of any time zone you want.

Edit: I actually didn't know JavaScript also had built in UTC time until I checked on the internet, neat.

In any case, I suppose this is want you want:

Date.prototype.format=function(format,timezone){
    var obj=new Date(this.getTime()+this.getTimezoneOffset()*60000+timezone*3600000);
    var two=function(s){
        return s<10?"0"+s:s+"";
    }
    return format.replace(/dd|MM|yyyy|hh|mm|ss/g, function(pattern){
        switch(pattern){
            case "dd" : return two(obj.getDate());
            case "MM" : return two(obj.getMonth()+1);
            case "yyyy" : return obj.getFullYear();
            case "hh" : return two(obj.getHours());
            case "mm" : return two(obj.getMinutes());
            case "ss" : return two(obj.getSeconds());
        }
    });
}

You can add in more patterns if you need.

eBusiness
eBusiness, I'm not asking two questions in one. In many programming languages, the Date object does not change with the timezone, it's the way it's displayed that changes. The date NOW is the same everywhere in the world but it's displayed differently.If you look at my Java Example, notice how I'm displaying the same Date object using two different Date Formats.
Elie
A: 

JavaScript does not have build in support for other time zone than the local one. You can only express a date in local time or in UTC time. There is no way to change the time zone offset of a Date object.

Thus, there is no "neat" way to solve your problem. For a hackish solution, you may want to check out this page.

KaptajnKold
+1  A: 

The ISO Extended format for common date is YYYY-MM-DD, and for time is hh:mm:ss. Either format can be understood, unambiguously, worldwide.

See also: http://jibbering.com/faq/#dates

Garrett