So I have iso date time that need to be converted from a string to date object. How do I keep date from converting it to local browser timezone.
new Date('2013-07-18T17:00:00-05:00')
Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)
I want to get
Thu Jul 18 2013 17:00:00 GMT-0500 (XX)
While MomentJS is a great library, it may not provide a solution for every use case. For example, my server provides dates in UTC, and when the time portion of the date is not saved in the db (because it's irrelevant), the client receives a string that has a default time of all zeros - midnight - and ends with an offset of +0000. The browser then automatically adjusts for my local time zone and pulls the time back by a few hours, resulting in the previous day.
This is true with MomentJs as well.
One solution is to slice off the time portion of the string, and then use MomentJS as described in the other answers.
But what happens if MomentJS is not a viable option, i.e. I already have many places that use a JS Date and don't want to update so many lines of code? The question is how to stop the browser from converting dates based on local time zone in the first place. And the answer is, when the date is in ISO format, you cannot.
However, there is no rule that says the string you pass to JavaScript's Date constructor must be in ISO format. If you simply replace the - that separates the year, month, and day with a /, your browser will not perform any conversion.
In my case, I simply changed the format of the Dates server-side, and the problem was solved without having to update all the client-side JS dates with MomentJS.
Note that the MDN docs for JavaScript's Date class warn about unpredictable browser-behavior when parsing a string to create a Date instance.
You cannot change this behavior of Javascript because it is the only simple way for Javascript to work. What happens is simply that Javascript looks at the time shift, computes the matching timestamp, and then asks the OS for the representation of this timestamp in the local time zone. What is key to understand here is that -05:00 is not an indication of time zone but simply a shift from UTC.
Time zones are complex beasts that are just arbitrary political decisions. The OS provides a service to display time in the local time zone, but not in other time zones. To do that you have to take in account things like DST that are pretty much a hell.
As always with time management, the only decent way to tackle this problem is to use a dedicated library. In Javascript, you'll find Moment.js and Moment.Timezone.js very helpful.
Example http://codepen.io/Xowap/pen/XKpKZb?editors=0010
document.write(moment('2013-07-18T17:00:00-05:00').tz('America/New_York').format('LLL'));
As a bonus, you get a ton of formatting/parsing features from Moment.js.
Please also note that as long as you use the ISO 8601, your date can be pinpointed to a precise moment, and thus be displayed in any timezone of your liking. In other words, JS "converting" your date doesn't matter.
You can use a library such as Moment.js to do this.
See the String + Format parsing.
http://momentjs.com/docs/#/parsing/string-format/
The following should parse your date you provided, but you may need to modify it for your needs.
var dateString = "2013-07-18T17:00:00-05:00";
var dateObject = moment(dateString, "YYYY-MM-DDTHH:mm:ssZ").toDate();
Alternatively, see Moment's String parser, which looks like it is in the format you provided, with the exception of a space between the seconds of the time and the time zone.
http://momentjs.com/docs/#/parsing/string/
This is an old question that recently got linked in an answer to a newer question, but none of the existing answers seem to fully address the original question.
In many cases the easiest way to format and display a datetime string in the time zone that it is received, is not to convert the string to a Date object at all. Instead, just parse the datetime string and recombine the parts into the desired format. For example, if you can live without the day of the week in the output requested in the question, you could do something like the following to handle the requested input and output format (including the day of the week adds enough complexity that it might be worth using a library at that point). Of course, this approach requires modification based on the format of the datetime strings you are receiving on the client side.
const months = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'};
const format = (datetime) => {
const [date, time] = datetime.split('T');
const [y, m, d] = date.match(/\d+/g);
const [t, tz] = time.split(/(?=[+-])/);
return `${months[Number(m)]} ${d} ${y} ${t} GMT${tz}`;
};
const dt = format('2013-07-18T17:00:00-05:00');
console.log(dt);
// Jul 18 2013 17:00:00 GMT-05:00
There are JavaScript and other library methods that will allow you to convert your datetime string to a Date instance and then display it in a specific time zone if you are consistently receiving datetime strings from one or a few specific time zones that are easily identified on the client side. Following are a couple of examples.
toLocaleString enables you to display a date in a specific time zone but the options parameters required to set the time zone are not supported across all browsers (as of the date of this answer). For example (note that parsing of date strings with the Date constructor is still discouraged, but most modern browsers will handle an ISO 8601 format string like the one below):
const dt = new Date('2013-07-18T17:00:00-05:00');
const ny = dt.toLocaleString('en-US', { timeZone: 'America/New_York' });
console.log(`Local: ${dt}`);
console.log(`New York: ${ny}`);
You could also use Moment.js with Moment Timezone to display a date in a specific time zone. For example:
const ny = moment('2013-07-18T17:00:00-05:00').tz('America/New_York').format();
console.log(`New York: ${ny}`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data.min.js"></script>
It is important to note the following when working with datetime strings and time zones in JavaScript. The JavaScript Date constructor DOES NOT change the time zone offset. When you create a date from a string using ISO 8601 format as in the question example, Date does the following:
Creates a JavaScript Date instance that represents a single moment in
time. Date objects use a Unix Time Stamp, an integer value that is the
number of milliseconds since 1 January 1970 UTC.
In other words, JavaScript Date instances do not store (or change) time zone offsets. The reason you often see output from a JavaScript Date in your local time zone is that toString is the default method called when you log a Date instance to the console (or use various other approaches to output your date). In most browser implementations, this method relies on the browser's local time zone to convert the number of milliseconds since 1 January 1970 UTC into a string representation of the date.
Wonder if this would help:
function goAheadMakeMyDate(s){
var d = new Date(s);
// override Date.toString()
d.toString = function(){ return ''+s; };
return d;
}
var example = goAheadMakeMyDate("Fri 19 July 2013 12:00:00 GMT");
example.toString() // returns string actually used to construct the date
'Fri 19 July 2013 12:00:00 GMT'
example.toLocaleString()
'Fri Jul 19 2013 08:00:00 GMT-0400 (EDT)'
1*example // gives seconds since epoch
1374235200000
With your input:
example = goAheadMakeMyDate('2013-07-18T17:00:00-05:00')
{ Thu, 18 Jul 2013 22:00:00 GMT toString: [Function] }
> example.toString()
'2013-07-18T17:00:00-05:00'
> example.toLocaleString() // I live in GMT-4
'Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)'
> 1*example // convert to integer date
1374184800000
However, if you start modifying this date, the toString will not change and will bite you.
I have a scenario where date time stamp needs to update only once. In detail I have button in my application and when clicked on it will generate a PDF along with timestamp footer and when refreshed it should not change date time.
For the above scenario I have used localStorage.setItem('','') and getItems. In precise.... when clicked on generate button I have used localStorage.setItem('','') and in the generating footer logic I have used localStorage.getItem('') dats it....
Explanation for above logic:
Whenever we are generating I am setting current date time and when generating am calling getItem which will pick the set date time from local storage.
This will reset again when clicked on Generate button.
Hope this helps someone in need..... :-)
Related
I use ExcelJS to parse an Excel into a JavaScript Object.
Here is an excel sample :
As you can see, I must cover multiple format for date and hour. For the date I have no problem. But when it comes to hour, cells with "12:30" and "15:00" value are returned as javascript date object. So I check if its a date or a string and I want to get the string value (10H10 and 18h30 cells are ok because they are considered as string but not the 15:00 and 12:30).
When using VSCode debug tool, I can see that I have this date :
'Sat Dec 30 1899 12:39:21 GMT+0009 (Central European Standard Time)'
'Sat Dec 30 1899 15:09:21 GMT+0009 (Central European Standard Time)'
What I want is a way to cast this result in a string "12:30" or "15:30". I tried many things using moment and Date functions like .toUTCString(), .toGMTString()...
I'm going to assume you have a JS Date object.
Intl.DateTimeFormat would be recommended for formatting date and/or times for users.
But since you want a specific format, it might be easier to format it yourself.
But the time isn't in the correct time zone. You'd first have to convert it to the correct time zone. Except the correct time zone is UTC, and we can access that info about the components of the UTC representation of the date-time without doing any conversion.
[
dt.getUTCHours(),
dt.getUTCMinutes().toString().padStart(2, '0'),
].join(":")
I have dates stored in my database in UTC format and calling
element.createdDate = new Date(element.createdDate.toString());
results in displaying the wrong date.
calling
element.createdDate = new Date(element.createdDate.toUTCString());
returns nothing. How do I go about displaying the correct time from UTC?
It appears that your json response contains a string valued which are in ISO8601 format in UTC, and then you are creating Date objects from them.
This part of your code is fine:
if (element.createdDate) element.createdDate = new Date(element.createdDate.toString());
You parse the string, and the resulting Date object is correct.
However, you don't need to use .toString() here, as the value is already a string. That is redundant.
This part of your code is the problem:
console.log("javascript date: " + new Date(element.depositDate.getUTCDate().toString()));
The getUTCDate function returns just the date of the month. Don't use that.
No matter what you do to create the Date object, ultimately you create a Date object and you're relying upon an implicit string conversion to output it. This will have different behavior in different browsers.
Consider console.log(new Date()):
In Chrome, this logs something like Fri Mar 17 2017 12:14:29 GMT-0700 (Pacific Daylight Time) on my computer. This is as if I called console.log(new Date().toString()); It is in an RFC 2822 like format (but not quite), and is represented in local time.
In Firefox, this logs something like 2017-03-17T19:14:46.535Z. This is as if I called console.log(new Date().toISOString()); It is in ISO8601 format, and is represented in UTC.
The point is, don't rely on implicit undefined behavior. If you must work with Date objects, then you should use console.log(element.createdDate.toISOString()) to see the ISO8601 representation of the UTC time.
If you're going to be doing a lot of things with dates and times, you may prefer to use a library, such as Moment.js, which can make tasks such as this more clear.
I have dates stored in my database in UTC format and calling
element.createdDate = new Date(element.createdDate.toString());
results in displaying the wrong date.
2016-10-11T00:00:00Z and Mon Oct 10 2016 20:00:00 GMT-04:00 (EDT) are exactly the same moment in time. The only difference is that one is displayed in ISO 8601 extended format with timezone offset 00:00 and the other is displayed in an RFC 2822 (like) format with timezone offset -04:00 (and assumes a locality in the EDT region).
calling
element.createdDate = new Date(element.createdDate.toUTCString());
returns nothing.
That is unusual. Typically it would return either a string or an error, but without a working example or any code to provide context it's impossible to say why.
How do I go about displaying the correct time from UTC?
You haven't specified what "correct" is. You are displaying a date and time for the same moment in time, just in a different format and time zone.
I have div in which I am providing date and time like this
<div class="timing">
<div id="count-down" data-date="2016-08-31 14:21:00"> </div>
</div>
How would I match or compare with current date, because I am getting current date in this format Wed Aug 31 2016 14:34:58 GMT+0500 (Pakistan Standard Time)
I want to redirect a page to new location if current date is greater than provided date
var currentDate = new Date();
var providedDate = $('#count-down').attr('data-date')
if (currentDate.getDate().toString > providedDate)
{
window.location.href = 'Promo';
$('.timing').css("display", "none");
$('.website-loading').css("display", "block");
}
I have div in which I am providing date and time like this
<div id="count-down" data-date="2016-08-31 14:21:00"> </div>
The string in the data- attribute is not consistent with the format specified in ECMA-262 (the "T" separator between the date and time is missing), so you should manually parse it by either writing a parsing function or use a library and provide the format to parse.
If you use the Date constructor (or Date.parse, they are equivalent for parsing) to parse the string, you may get an invalid date (e.g. in Safari, new Date('2016-01-01 12:00:00') produces an invalid date) since parsing of non–standard strings is entirely implementation dependent.
There are many suitable libraries, some suggestions:
moment.js does parsing, formatting, timezones and arithmetic and has a CDN
fecha.js just does parsing and formatting is very much smaller than moment.js
When you create a Date object, it only has one internal value (called its time value), which is milliseconds since 1970-01-01T00:00:00Z (the javascript epoch, which is the same as the UNIX epoch). When you call the toString method, the result is an implementation dependent string that differs between implementations (in your case you see something like "Wed Aug 31 2016 14:34:58 GMT+0500 (Pakistan Standard Time)", a different implementation may produce something else.
How would I match or compare with current date, because I am getting
current date in this format Wed Aug 31 2016 14:34:58 GMT+0500 (Pakistan Standard Time)
When comparing dates, you really just want to compare the time value. If you compare using the relational operators > or <, they will coerce the dates to their time value so you can compare the dates directly, e.g.:
var providedDate = fecha.parse($('#count-down').attr('data-date'), 'YYYY-MM-DD HH:mm:ss');
if (Date.now() > providedDate) {
// providedDate is in the past
}
Note that since no time zone information is provided in the string to parse, it's treated as a "local" date and time and the host system's current settings are used to determine the offset from UTC, which is then used when calculating the time value. The same system works in reverse when generating a local date and time string from the Date using the default toString method.
Also:
currentDate.getDate()
just returns the date (i.e. the day in the month) as a number without the year and month.
I am based in Australia and while new Date() give me the current date and time in Australia, for instance
Fri Aug 26 2016 09:16:16 GMT+1000 (AUS Eastern Standard Time)
, if I write new Date().toJSON()
I get 2016-08-25T23:20:08.242Z,
how can I get the same format as in yyyy-mm-ddThh:mn:ss but keeping my local day and time, ie it should be the 26 and not the 25th.
Edit: when I write programmatically new Date(2016, 11, x) with var x = 31, using toJSON() I have no guarantee to see displayed 2016-12-31 because of timezones, so was wondering is there is a different javascript function that would give me the intended result.
I would use moment.js for that.
var date = moment("Fri Aug 26 2016 09:16:16 GMT+1000");
console.log(moment(date).format('YYYY-MM-DD T hh:mm:ss'));
https://jsfiddle.net/Refatrafi/ys4nu8o9/
toJSON() returns timestamps in ISO 8601 format. Z at the end of string means that used UTC. Date objects in ECMAScript are internally UTC. The specification for Date.prototype.toJSON says that it uses Date.prototype.toISOString, which states that "the timezone is always UTC".
The date isn't wrong, it's in UTC. Without timezone information, yyyy-mm-ddThh:mn:ss is meaningless unless you explicitly want to assume that it's in the AEST timezone.
If you're transmitting the date as a string to be parsed back into some sort of Date-like object later on (by your webserver, for example), there's nothing you need to do. 2016-08-25T23:20:08.242Z unambiguously refers to the same point in time no matter what you use to parse it.
If you're trying to format the date object and display it somewhere, you can extract the different parts of the Date object and build up the representation you want:
function format_date(d) {
var pretty_date = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join('-');
var pretty_time = [d.getHours(), d.getMinutes(), d.getSeconds()].join(':');
return pretty_date + 'T' + pretty_time;
}
As the other answers have pointed out, if you plan on working more with dates, consider using a library that makes it easier. JavaScript doesn't have a very rich API, so you'll have to write more code.
This question already has an answer here:
HTML Input type datetime-local setting the wrong time-zone
(1 answer)
Closed 7 years ago.
I'm writing a MVC 5 web application. Into this, I have multiple lists that I propagate and manage through javascript and jquery (one dataset, dependent select controls, and adding ajax callbacks would complicate it unnecessarily.)
The issue I have is: I have a hidden for field formatted to ISO 8601. I run into issues when I display the date in the user's local time, I get a shifted date.
So if the date were stated as: 01-01-2009 (in iso 8601 format: 2009-01-01), the user sees: 12-31-2008.
When I parse the date I'm using:
this.date = new Date(Date.parse(originalString));
/* ^- Date.parse is giving me a number. */
To display the text of the date I am using:
admin.date.toLocaleDateString().Concat(...
Do I need to do any sort of patch-up to adjust things to the proper time-zone? The date, when using console.log(admin.date); shows the original 2009-01-01
I'm thinking there's some parameter I'm not specifying correctly in the toLocaleDateString, but my familiarity level with it is low.
Edit: The goal is to prevent the date shift. All we store is the date, the time aspect is dropped. We have multiple time-zones posting to this database, and the goal is: We use the date of the person who posted it, time dropped. Were the date May 01, 2015, I want anyone who sees that date to see May 01, 2015, the 'toLocaleDateString' is merely a means to get it to appear format correct for their region. So someone who views dates as yyyy-mm-dd will see it properly.
Based on the documentation for Date.parse:
The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC.
You are getting back the epoch time in UTC for your parsed date string hence why the date is off for local times. So, you would need to know the time difference between the local time and UTC which Date.getTimezoneOffset provides (in minutes) in order to set the correct date for the local time:
> var date = new Date(Date.parse('2009-01-01'));
undefined
> date;
Wed Dec 31 2008 19:00:00 GMT-0500 (EST)
> date.getTimezoneOffset();
300
> date.setMinutes(date.getTimezoneOffset());
1230786000000
> date;
Thu Jan 01 2009 00:00:00 GMT-0500 (EST)
One thing to note though is:
...the offset is positive if the local timezone is behind UTC and negative if it is ahead.
So you might need to take care for locales where the value is negative if this applies to your application. If so maybe just omitting negative values would be enough since the date should be the same if a locale's timezone is ahead of midnight UTC.
EDIT: To compensate for possible issues with daylight savings time:
> var dateVals = String.prototype.split.call('2009-01-01', '-');
undefined
> var date = new Date(dateVals[0], dateVals[1] - 1, dateVals[2]);
undefined
> date
Thu Jan 01 2009 00:00:00 GMT-0500 (EST)