Reputation: 7363
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
Upvotes: 18
Views: 83922
Reputation: 1
This is a JavaScript port of PHP's date function:
e.g.
console.log( new Date("2023-01-01").return("M d Y") )
returns "JAN 01 2023"
console.log ( new Date("1980-01-01").return("\\\\D\\\\av\\\\i\\\\d \\\\w\\\\a\\\\s bor\\\\n o\\\\n M d Y \\\\a\\\\n\\\\d \\\\here'\\\\s t\\\\he e\\\\s\\\\c\\\\ape \\\\c\\\\h\\\\ar \\\\\\")
returns "David was born on JAN 01 1980 and here's the escape char \\"
if (!Date.prototype.return) {
Date.prototype.return = function (format) {
if (isNaN(this.valueOf()) || !this.valueOf()) { return null; }
let days = ["SUN", "MON", "TUE", "WED", "THR", "FRI", "SAT"];
let months = ["JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"];
let newDate = new Date(this.getTime() + this.getTimezoneOffset() * 60000);
let month = newDate.getMonth();
let weekDay = newDate.getDay();
let day = newDate.getDate();
let year = newDate.getFullYear();
let hour = newDate.getHours();
let minute = newDate.getMinutes();
let second = newDate.getSeconds();
let string = [];
let escapeNext = false;
for (const character of format) {
if (escapeNext) {
string.push(character);
escapeNext = false;
} else if (character === "\\") {
escapeNext = true;
} else {
switch (character) {
case "a": string.push(hour < 12 ? "AM" : "PM"); break;
case "c": string.push(newDate.toISOString()); break;
case "d": string.push(String("0" + day).slice(-2)); break;
case "D": string.push(days[weekDay]); break;
case "F": string.push(months[month]); break;
case "g": let h = hour === 0 ? 12 : hour;
string.push(h > 12 ? h - 12 : h);
break;
case "h": h = hour === 0 ? 12 : hour;
h = h > 12 ? h - 12 : h;
string.push(String("0" + h).slice(-2));
break;
case "H": string.push(String("0" + hour).slice(-2)); break;
case "i": string.push(String("0" + minute).slice(-2)); break;
case "j": string.push(day); break;
case "l": string.push(days[weekDay]); break;
case "m": string.push(String("0" + (month + 1)).slice(-2)); break;
case "M": string.push(months[month].substring(0, 3)); break;
case "n": string.push(month + 1); break;
case "s": string.push(String("0" + second).slice(-2)); break;
case "w": string.push(weekDay); break;
case "y": string.push(year.toString().slice(-2)); break;
case "Y": string.push(year); break;
default : string.push(character);
}
}
}
return string.join("");
};
}
Upvotes: 0
Reputation: 730
There is a way to format for time zones.
console.log(new Date().toLocaleDateString('en-US', {timeZone: 'America/Denver'}))
// 11/13/2018
console.log(new Date().toLocaleTimeString('en-US', {timeZone: 'America/Denver'}))
// 2:30:54 PM
console.log(new Date().toLocaleTimeString('en-US', {timeZone: 'America/New_York'}))
// 4:31:26 PM
Upvotes: 27
Reputation: 1250
Since my requirement was a typescript solution but I stumbled here I used this answer to write my typescript function.
Based on answer above, a function in typescript which converts a timestamp or a date object into a formatted local time string.
const formatDateString = (date_or_ts:Date|number):string=>{
let obj:Date;
if(typeof date_or_ts === "number"){
obj = new Date(date_or_ts*1000);
// obj=new Date(obj.getTime()+obj.getTimezoneOffset()*60000+timezone*3600000);
}else{
obj = date_or_ts;
}
const format = "dd-MM-yyyy hh:mm:ss";
let two=function(s:number){
return s<10?"0"+s:s+"";
}
return format.replace(/dd|MM|yyyy|hh|mm|ss/g, function(pattern){
const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
switch(pattern){
case "dd" : return two(obj.getDate()).toString();
case "MM" : return months[obj.getMonth()];
case "yyyy" : return obj.getFullYear().toString();
case "hh" : return two(obj.getHours()).toString();
case "mm" : return two(obj.getMinutes()).toString();
case "ss" : return two(obj.getSeconds()).toString();
default: return "";
}
});
}
Upvotes: 0
Reputation: 16284
This is an old question, but since I found it:
As mentioned, there's nothing reasonable built-in.
As for libs, there is Moment Timezone for Moment.js.
Here is a JSfiddle with an example: http://jsfiddle.net/kunycrkb/
The same code inline:
var m = moment("2014-06-01T13:05:00Z");
var f = "HH:mm z";
$("#results").text(m.tz("UTC").format(f) + " is " + m.tz("EST").format(f) + "!");
Upvotes: 1
Reputation: 3023
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
Upvotes: 3
Reputation: 3700
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.
Upvotes: 1
Reputation: 14606
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
});
}
Upvotes: 1
Reputation: 413757
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);
Upvotes: 0
Reputation: 4132
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());
}
});
}
Upvotes: 1