I have different timestamps and a timezones coming from an API as an object. Example:
{{'ts' : 1521311400000},
{'tz' : 'GMT+01:00'}}
How can I convert the timestamp to a human readable Date in that timezone using toLocaleTimeString()? I have tried to pass the timezone inside the options object as the value for timeZone as stated here but I get an invalid time zone in DateTimeFormat() Error and cant figure out how the correct Format should be.
To get that kind of flexibility in formatting dates, you'll probably want to look into Moment and Moment Timezone.
If you'd like another option, you could try this:
function init() {
function formatFixedTimeZone(ts, tz) {
let offsetStr = tz.replace(/:/g, '');
let reverseOffset = offsetStr.replace(/[-+]/, sign => sign === '+' ? '-' : '+');
let time = new Date(ts);
let timeStr = time.toUTCString().replace('GMT', reverseOffset);
time = new Date(Date.parse(timeStr));
timeStr = time.toLocaleString('en-US', {
timeZone: 'UTC', // Don't change this from UTC for other time zones.
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}) + ' ' + tz;
return timeStr;
}
let timeDisplay = document.getElementById('time');
function tick() {
let nowStr = formatFixedTimeZone(Date.now(), 'GMT+01:00');
timeDisplay.textContent = nowStr;
}
setInterval(tick, 1000);
}
Plunker here: http://plnkr.co/edit/Gk6SOLwpWqfoT5gHlCrb?p=preview
This displays a running count of the current time in a fixed time zone, but I've tried to write it in such a way that if you aren't using the current time, but the ts and tz values from your API, it shouldn't be too hard to adapt this to your needs and to different output formatting.
I am using momentjs but having an issue trying to convert a UTC time to a specific timezone (not necessarily local to the current user) that is specified by name 'America/New_York'. This SO question is similar but didn't really help.
My thought process is to create a utc moment obj with the received date from the server and then format that UTC time to the specific timezone for display purposes. A small snippet of how I'm currently approaching this:
var cutoffString = '20170421 16:30:00'; // in utc
var utcCutoff = moment.tz(cutoffString, 'YYYYMMDD HH:mm:ss', '+00:00');
var displayCutoff =
moment.tz(utcCutoff.format('YYYYMMDD HH:mm:ss'), 'YYYYMMDD HH:mm:ss', 'America/New_York');
console.log('utcCutoff:', utcCutoff.format('YYYYMMDD hh:mm:ssa Z')); // => utcCutoff: 20170421 04:30:00pm +00:00
console.log('displayCutoff:', displayCutoff.format('YYYYMMDD hh:mm:ssa Z')); // => displayCutoff: 20170421 04:30:00pm +00:00
My assumption here is that displayCutoff would be the utcCutoff time displayed in 'America/New_York' time. But it currently is displays the same time as the utcCutoff object. I also should mention that using .utc() instead of .tz and trying to manipulate the timezone after applying .local() did not work either.
Any help/guidance would be appreciated.
You can use moment.utc since your input is an UTC string. You can use tz to convert your moment object to a given timezone.
Please note that the tz function converts moment object to a given zone, while you are using moment.tz parsing function that builds a new moment object with the given zone. When you do:
var displayCutoff =
moment.tz(utcCutoff.format('YYYYMMDD HH:mm:ss'), 'YYYYMMDD HH:mm:ss', 'America/New_York');
you are not converting utcCutoff to 'America/New_York' but you are building a new moment object for 20170421 16:30:00 in New York.
Here an updated version of your code:
var cutoffString = '20170421 16:30:00'; // in utc
var utcCutoff = moment.utc(cutoffString, 'YYYYMMDD HH:mm:ss');
var displayCutoff = utcCutoff.clone().tz('America/New_York');
console.log('utcCutoff:', utcCutoff.format('YYYYMMDD hh:mm:ssa Z')); // => utcCutoff: 20170421 04:30:00pm +00:00
console.log('displayCutoff:', displayCutoff.format('YYYYMMDD hh:mm:ssa Z')); // => displayCutoff: 20170421 12:30:00pm -04:00
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.11/moment-timezone-with-data-2010-2020.min.js"></script>
Moment timezone plugin is exactly what you need : http://momentjs.com/timezone/
var dec = moment("2014-12-01T12:00:00Z");
dec.tz('America/New_York').format('ha z'); // 5am PDT
With momentjs-timezone you can convert from any timezone to any other timezone.
You need to specify the start time zone and before formatting the target timezone.
Here is an example which converts a date time from UTC to three other timezones:
const moment = require('moment-timezone')
const start = moment.tz("2021-12-08T10:00:00", "UTC") // original timezone
console.log(start.tz("America/Los_Angeles").format())
console.log(start.tz("Asia/Calcutta").format())
console.log(start.tz("Canada/Eastern").format())
This will print out:
2021-12-08T02:00:00-08:00
2021-12-08T15:30:00+05:30
2021-12-08T05:00:00-05:00
Instead of UTC as start timezone you can use any other timezone too, like "Asia/Seoul" and obviously get different results with the same script:
const moment = require('moment-timezone')
const start = moment.tz("2021-12-08T10:00:00", "Asia/Seoul")
console.log(start.tz("America/Los_Angeles").format())
console.log(start.tz("Asia/Calcutta").format())
console.log(start.tz("Canada/Eastern").format())
This prints out:
2021-12-07T17:00:00-08:00
2021-12-08T06:30:00+05:30
2021-12-07T20:00:00-05:00
All momentjs timezones are listed here:
https://gist.github.com/diogocapela/12c6617fc87607d11fd62d2a4f42b02a
There is no need to use MomentJs to convert your timezone to specific timezone. Just follow my given below code, it will work for you :
$(document).ready(function() {
//EST
setInterval( function() {
var estTime = new Date();
var currentDateTimeCentralTimeZone = new Date(estTime.toLocaleString('en-US', { timeZone: 'America/Chicago' }));
var seconds = currentDateTimeCentralTimeZone.getSeconds();
var minutes = currentDateTimeCentralTimeZone.getMinutes();
var hours = currentDateTimeCentralTimeZone.getHours();//new Date().getHours();
var am_pm = currentDateTimeCentralTimeZone.getHours() >= 12 ? "PM" : "AM";
if (hours < 10){
hours = "0" + hours;
}
if (minutes < 10){
minutes = "0" + minutes;
}
if (seconds < 10){
seconds = "0" + seconds;
}
var mid='PM';
if(hours==0){ //At 00 hours we need to show 12 am
hours=12;
}
else if(hours>12)
{
hours=hours%12;
mid='AM';
}
var x3 = hours+':'+minutes+':'+seconds +' '+am_pm
// Add a leading zero to seconds value
$("#sec").html(x3);
},1000);
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<p class="date_time"><strong id="sec"></strong> </p>
</body>
</html>
Is there a way to create a countdown timer using javascript that will automatically adjust to a different countdown once it reaches 0? (Example: countdown from current time until New Year of 2012 and once it reaches 0 it will change to a countdown to a birthday that is in March) (this could be used as a countdown for a schedule for an event. you could have a schedule and a countdown to the next part of the schedule once it finishes counting down to the first part)
var timeForNextFunction = false;
function firstFunction(){
//set timeForNextFunction = true when its time for the next function.
};
function nextFunction(){};
var tick = 100; //milliseconds
document.setInterval(function(){
if (timeForNextFunction)
nextFunction();
else
firstFucntion();
}, tick);
You can have an array of Date, for example:
function newDate(seconds){
var d=new Date();
d.setTime(new Date().getTime()+1000*seconds);
return d;
}
var events=[newDate(10),newDate(40)];
And then
var currentEvent=0,
cntdwn=document.getElementById('seconds');
refreshEvent();
var timer=setInterval(display,1000);
function display(){
var seconds=Math.ceil((events[currentEvent].getTime()-new Date().getTime())/1000);
if(seconds>=0){
cntdwn.innerHTML=seconds;
}else{
if(currentEvent<events.length-1){
currentEvent++;
refreshEvent();
}else{
clearTimeout(timer);
// Finished
}
}
}
function refreshEvent(){
document.getElementById('currentDate').innerHTML=events[currentEvent];
}
See it here: http://jsfiddle.net/epUG4/
Sure, out of many countdowns, you can try jCounter and set its fallback to launch another instance of the plugin with another date.
This how you'd do it in jCounter:
$('.counterClass').jCounter({
date: '31 december 2012 23:59:59',
format: 'dd:hh:mm:ss', // display days, hours, minutes and seconds, you can choose here what to display
fallback: function() { $('.counterClass').jCounter({ // fallback for the next countdown
date: '31 march 2013 00:00:00',
format: 'dd:hh:mm:ss', // format
fallback : function() { alert("Happy Birthday!") } // second fallback
}); }
});
Take note that jCounter relies on server-side timezone, the default is 'Europe/London', you can change it by adding (among the other settings), timezone: 'Europe/Oslo', or whatever you please.
I want the server to always serve dates in UTC in the HTML, and have JavaScript on the client site convert it to the user's local timezone.
Bonus if I can output in the user's locale date format.
Seems the most foolproof way to start with a UTC date is to create a new Date object and use the setUTC… methods to set it to the date/time you want.
Then the various toLocale…String methods will provide localized output.
Example:
// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);
console.log(d); // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString()); // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString()); // -> 02/28/2004
console.log(d.toLocaleTimeString()); // -> 23:45:26
Some references:
toLocaleString
toLocaleDateString
toLocaleTimeString
getTimezoneOffset
You can do it with moment.js (deprecated in 2021)
It's best to parse your date string from UTC as follows (create an ISO-8601 compatible string on the server to get consistent results across all browsers):
var m = moment("2013-02-08T09:30:26Z");
Now just use m in your application, moment.js defaults to the local timezone for display operations. There are many ways to format the date and time values or extract portions of it.
You can even format a moment object in the users locale like this:
m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us
To transform a moment.js object into a different timezone (i.e. neither the local one nor UTC), you'll need the moment.js timezone extension. That page has also some examples, it's pretty simple to use.
Note: Moment JS recommends more modern alternatives, so it is probably not a good choice for new projects.
You can use new Date().getTimezoneOffset()/60 for the timezone. There is also a toLocaleString() method for displaying a date using the user's locale.
Here's the whole list: Working with Dates
In JS there are no simple and cross platform ways to format local date time, outside of converting each property as mentioned above.
Here is a quick hack I use to get the local YYYY-MM-DD. Note that this is a hack, as the final date will not have the correct timezone anymore (so you have to ignore timezone). If I need anything else more, I use moment.js.
var d = new Date();
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000)
var yyyymmdd = t.toISOString().slice(0, 10);
// 2017-05-09T08:24:26.581Z (but this is not UTC)
The d.getTimezoneOffset() returns the time zone offset in minutes, and the d.getTime() is in ms, hence the x 60,000.
2021 - you can use the browser native Intl.DateTimeFormat
const utcDate = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
console.log(new Intl.DateTimeFormat().format(utcDate));
// expected output: "21/04/2021", my locale is Switzerland
Below is straight from the documentation:
const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
// Results below assume UTC timezone - your results may vary
// Specify default date formatting for language (locale)
console.log(new Intl.DateTimeFormat('en-US').format(date));
// expected output: "12/20/2020"
// Specify default date formatting for language with a fallback language (in this case Indonesian)
console.log(new Intl.DateTimeFormat(['ban', 'id']).format(date));
// expected output: "20/12/2020"
// Specify date and time format using "style" options (i.e. full, long, medium, short)
console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'full', timeStyle: 'long' }).format(date));
// Expected output "Sunday, 20 December 2020 at 14:23:16 GMT+11"
Once you have your date object constructed, here's a snippet for the conversion:
The function takes a UTC formatted Date object and format string.
You will need a Date.strftime prototype.
function UTCToLocalTimeString(d, format) {
if (timeOffsetInHours == null) {
timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
}
d.setHours(d.getHours() + timeOffsetInHours);
return d.strftime(format);
}
// new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
var serverDate = new Date(2018, 5, 30, 19, 13, 15); // just any date that comes from server
var serverDateStr = serverDate.toLocaleString("en-US", {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
})
var userDate = new Date(serverDateStr + " UTC");
var locale = window.navigator.userLanguage || window.navigator.language;
var clientDateStr = userDate.toLocaleString(locale, {
year: 'numeric',
month: 'numeric',
day: 'numeric'
});
var clientDateTimeStr = userDate.toLocaleString(locale, {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log("Server UTC date: " + serverDateStr);
console.log("User's local date: " + clientDateStr);
console.log("User's local date&time: " + clientDateTimeStr);
Here's what I've used in past projects:
var myDate = new Date();
var tzo = (myDate.getTimezoneOffset()/60)*(-1);
//get server date value here, the parseInvariant is from MS Ajax, you would need to do something similar on your own
myDate = new Date.parseInvariant('<%=DataCurrentDate%>', 'yyyyMMdd hh:mm:ss');
myDate.setHours(myDate.getHours() + tzo);
//here you would have to get a handle to your span / div to set. again, I'm using MS Ajax's $get
var dateSpn = $get('dataDate');
dateSpn.innerHTML = myDate.localeFormat('F');
The .getTimezoneOffset() method reports the time-zone offset in minutes, counting "westwards" from the GMT/UTC timezone, resulting in an offset value that is negative to what one is commonly accustomed to. (Example, New York time would be reported to be +240 minutes or +4 hours)
To the get a normal time-zone offset in hours, you need to use:
var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60
Important detail:
Note that daylight savings time is factored into the result - so what this method gives you is really the time offset - not the actual geographic time-zone offset.
With date from PHP code I used something like this..
function getLocalDate(php_date) {
var dt = new Date(php_date);
var minutes = dt.getTimezoneOffset();
dt = new Date(dt.getTime() + minutes*60000);
return dt;
}
We can call it like this
var localdateObj = getLocalDate('2015-09-25T02:57:46');
I mix the answers so far and add to it, because I had to read all of them and investigate additionally for a while to display a date time string from db in a user's local timezone format.
The datetime string comes from a python/django db in the format: 2016-12-05T15:12:24.215Z
Reliable detection of the browser language in JavaScript doesn't seem to work in all browsers (see JavaScript for detecting browser language preference), so I get the browser language from the server.
Python/Django: send request browser language as context parameter:
language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html', { "language": language })
HTML: write it in a hidden input:
<input type="hidden" id="browserlanguage" value={{ language }}/>
JavaScript: get value of hidden input e.g. en-GB,en-US;q=0.8,en;q=0.6/ and then take the first language in the list only via replace and regular expression
const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w{2}\-\w{2}),.*/, "$1");
JavaScript: convert to datetime and format it:
var options = { hour: "2-digit", minute: "2-digit" };
var dt = (new Date(str)).toLocaleDateString(defaultlang, options);
See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
The result is (browser language is en-gb): 05/12/2016, 14:58
The best solution I've come across is to create [time display="llll" datetime="UTC TIME" /] Tags, and use javascript (jquery) to parse and display it relative to the user's time.
http://momentjs.com/ Moment.js
will display the time nicely.
You could use the following, which reports the timezone offset from GMT in minutes:
new Date().getTimezoneOffset();
Note :
- this function return a negative number.
getTimeZoneOffset() and toLocaleString are good for basic date work, but if you need real timezone support, look at mde's TimeZone.js.
There's a few more options discussed in the answer to this question
To convert date to local date use toLocaleDateString() method.
var date = (new Date(str)).toLocaleDateString(defaultlang, options);
To convert time to local time use toLocaleTimeString() method.
var time = (new Date(str)).toLocaleTimeString(defaultlang, options);
A very old question but perhaps this helps someone stumbling into this.
Below code formats an ISO8601 date string in a human-friendly format corresponding the user's time-zone and locale. Adapt as needed. For example: for your app, are the hours, minutes, seconds even significant to display to the user for dates more than 1 days, 1 week, 1 month, 1 year or whatever old?
Also depending on your application's implementation, don't forget to re-render periodically.
(In my code below at least every 24hours).
export const humanFriendlyDateStr = (iso8601) => {
// Examples (using Node.js):
// Get an ISO8601 date string using Date()
// > new Date()
// 2022-04-08T22:05:18.595Z
// If it was earlier today, just show the time:
// > humanFriendlyDateStr('2022-04-08T22:05:18.595Z')
// '3:05 PM'
// If it was during the past week, add the day:
// > humanFriendlyDateStr('2022-04-07T22:05:18.595Z')
// 'Thu 3:05 PM'
// If it was more than a week ago, add the date
// > humanFriendlyDateStr('2022-03-07T22:05:18.595Z')
// '3/7, 2:05 PM'
// If it was more than a year ago add the year
// > humanFriendlyDateStr('2021-03-07T22:05:18.595Z')
// '3/7/2021, 2:05 PM'
// If it's sometime in the future return the full date+time:
// > humanFriendlyDateStr('2023-03-07T22:05:18.595Z')
// '3/7/2023, 2:05 PM'
const datetime = new Date(Date.parse(iso8601))
const now = new Date()
const ageInDays = (now - datetime) / 86400000
let str
// more than 1 year old?
if (ageInDays > 365) {
str = datetime.toLocaleDateString([], {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
})
// more than 1 week old?
} else if (ageInDays > 7) {
str = datetime.toLocaleDateString([], {
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
})
// more than 1 day old?
} else if (ageInDays > 1) {
str = datetime.toLocaleDateString([], {
weekday: 'short',
hour: 'numeric',
minute: 'numeric',
})
// some time today?
} else if (ageInDays > 0) {
str = datetime.toLocaleTimeString([], {
timeStyle: 'short',
})
// in the future?
} else {
str = datetime.toLocaleDateString([], {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
})
}
return str
}
Inspired from: https://alexwlchan.net/2020/05/human-friendly-dates-in-javascript/
Tested using Node.js
Don't know how to do locale, but javascript is a client side technology.
usersLocalTime = new Date();
will have the client's time and date in it (as reported by their browser, and by extension the computer they are sitting at). It should be trivial to include the server's time in the response and do some simple math to guess-timate offset.