I want to take date in my module with JSON format and when I am converting my date value to json then it changes the timezone ultimately date gets change for eg
var myDateWithJson=(new Date(2014, 03, 11).toJSON());
alert("Date With Json " +myDateWithJson);
var myDateWithoutJson = new Date(2014,03,11);
alert("Date Without Json " + myDateWithoutJson);
I also gone through covert json without timezone but, I don't think that is better approch
Please guide me for the better approch
In your code:
var myDateWithJson=(new Date(2014, 03, 11).toJSON());
will create a date object for 00:00:00 on the morning of 11 April 2014 (note that months are zero indexed here) in your current locale based on system settings. Calling toJSON returns an ISO 8601 date and time string for the equivalent moment based on UTC.
The date object will have an internal time value that is milliseconds since 1970-01-01T00:00:00Z.
var myDateWithoutJson = new Date(2014,03,11);
That creates a date object for exactly the same moment in time, i.e. with exactly the same time value.
alert("Date Without Json " + myDateWithoutJson);
That calls the toString method of the date object that returns a human readable string representing the date and time in the current locale based on system settings.
So the first is a UTC string, the second is a local string. Both represent the exact same instant in time, and, if converted back to Date objects, will have exactly the same internal time value.
Related
The server side is in C# and it returns object array list as json format. There is one field in the object model, it is DateTime type, and its value is DateTime.MinValue.
While in the page side, it receives /Date(-62135596800000)/ in string. I guess this is because of the object is serialized. And in javascirpt, I try to convert it back to Date type.
var timeSpan = element.DateModify.replace('Date','').replace('(','').replace(')','').replace(/\//g,'');
console.log(timeSpan);
var d = new Date(parseInt(timeSpan));
console.log(d);
When converted to Date in javascript, its value is 0001-01-01 08:05:43, not 0001-01-01 00:00:00. Why is it?
DateTime.MinValue is 0001-01-01 00:00:00 UTC. And that is indeed 0001-01-01 08:05:43 in your local time zone (whatever that may be, probably Asia/Shanghai or somewhere near that). When you console.log a Date, it displays the date in your local time zone. The Date value is correct. It's just displayed in a different format.
The extra 5 minutes and 43 seconds is because at the year AD 1, time zones have not been standardised, and the local mean time offset from UTC at your location is +08:05:43.
Two simple ways to make it display the UTC time of 00:00:00 is to call toISOString or toUTCString:
console.log(new Date(-62135596800000).toISOString());
console.log(new Date(-62135596800000).toUTCString());
I wish to create a new Date in JS, but have it be cast as UTC time. For example, suppose castAsUTC() produces the following desired effect:
var x = new Date('2019-01-01T00:00:00') // In local time (PST)
castAsUTC(x).toISOString(); // => '2019-01-01T00:00:00Z'
// x.toISOString() gives us '2019-01-01T08:00:00Z', which is undesired
Currently, my function looks like this:
function castAsUTC(date) {
return new Date(x.toLocaleString() + '+00:00');
}
Is there a cleaner/nicer way of producing the same effect? Thanks in advance!
EDIT: To be more specific, I'm interested in transforming the date's timezone, without changing its actual value with as little arithmetic as possible. So calling .toISOString() will produce the same date as it is in local time.
I am currently using the moment-timezone library, but I can't seem to get the desired effect using that, either. I would definitely accept an answer that uses Moment.js
You can switch a Moment instance to UTC using the utc function. Then just use format to get whatever the specific output you want from it.
If indeed the string you have is like the one shown, then the easiest thing to do would be to append a Z to indicate UTC.
var input = '2019-01-01T00:00:00';
var date = new Date(input + 'Z');
var output = date.toISOString();
Or, if you would like to use Moment.js, then do this:
var input = '2019-01-01T00:00:00';
var m = moment.utc(input);
var output = m.format();
You do not need moment-timezone for this.
tl;dr;
You formatted the date wrong. Add the letter "Z" to the end of your date string and it will be treated as UTC.
var x = new Date('2019-01-01T00:00:00Z') // Jan 1, 2019 12 AM UTC
These formatting issues are easier to manage with a library like momentjs (utc and format functions) as described in other answers. If you want to use vanilla javascript, you'll need to subtract out the timezone offset before calling toISOString (see warnings in the longer answer below).
Details
Date in javascript deals with timezones in a somewhat counter intuitive way. Internally, the date is stored as the number of milliseconds since the Unix epoch (Jan 1, 1970). That's the number you get when you call getTime() and it's the number that's used for math and comparisons.
However - when you use the standard string formatting functions (toString, toTimeString, toDateString, etc) javascript automatically applies the timezone offset for the local computers timezone before formatting. In a browser, that means it will apply the offset for the end users computer, not the server. The toISOString and toUTCString functions will not apply the offset - they print the actual UTC value stored in the Date. This will probably still look "wrong" to you because it won't match the value you see in the console or when calling toString.
Here's where things really get interesting. You can create Date's in javascript by specifying the number of milliseconds since the Unix epoch using new Date(milliseconds) or by using a parser with either new Date(dateString). With the milliseconds method, there's no timezone to worry about - it's defined as UTC. The question is, with the parse method, how does javascript determine which timezone you intended? Before ES5 (released 2009) the answer was different depending on the browser! Post ES5, the answer depends on how you format the string! If you use a simplified version of ISO 8601 (with only the date, no time), javascript considers the date to be UTC. Otherwise, if you specify the time in ISO 8601 format, or you use a "human readable" format, it considers the date to be local timezone. Check out MDN for more.
Some examples. I've indicated for each if javascript treats it as a UTC or a local date. In UTC, the value would be Jan 1, 1970 at midnight. In local it depends on the timezone. For OP in pacfic time (UTC-8), the UTC value would be Jan 1, 1970 at 8 AM.
new Date(0) // UTC (milliseconds is always UTC)
new Date("1/1/1970"); // Local - (human readable string)
new Date("1970-1-1"); // Local (invalid ISO 8601 - missing leading zeros on the month and day)
new Date("1970-01-01"); // UTC (valid simplified ISO 8601)
new Date("1970-01-01T00:00"); // Local (valid ISO 8601 with time and no timezone)
new Date("1970-01-01T00:00Z"); // UTC (valid ISO 8601 with UTC specified)
You cannot change this behavior - but you can be pedantic about the formats you use to parse dates. In your case, the problem was you provided an ISO-8601 string with the time component but no timezone. Adding the letter "Z" to the end of your string, or removing the time would both work for you.
Or, always use a library like momentjs to avoid these complexities.
Vanilla JS Workaround
As discussed, the real issue here is knowing whether a date will be treated as local or UTC. You can't "cast" from local to UTC because all Date's are UTC already - it's just formatting. However, if you're sure a date was parsed as local and it should really be UTC, you can work around it by manually adjusting the timezone offset. This is referred to as "epoch shifting" (thanks #MattJohnson for the term!) and it's dangerous. You actually create a brand new Date that refers to a different point in time! If you use it in other parts of your code, you can end up with incorrect values!
Here's a sample epoch shift method (renamed from castAsUtc for clarity). First get the timezone offset from the object, then subtract it and create a new date with the new value. If you combine this with toISOString you'll get a date formatted as you wanted.
function epochShiftToUtc(date) {
var timezoneOffsetMinutes = date.getTimezoneOffset();
var timezoneOffsetMill = timezoneOffsetMinutes * 1000 * 60;
var buffer = new Date(date.getTime() - timezoneOffsetMill);
return buffer;
}
epochShiftToUtc(date).toUTCString();
I have built an application that is using pure javascript Date objects and date-fns for formatting and manipulating the objects.
The application functions perfectly in GMT where I developed it however I'm now on the West Coast of The States and I've discovered that many of my date objects are thrown out because of the timezone difference.
I am creating date objects from strings, either just YYYY-MM-DD or YYYY-MM-DD HH:mm, for example new Date('2018-01-19') or new Date('2018-01-19 08:00').
The issue is that when I create a date from a string of the format YYYY-MM-DD it creates the object disregarding the local timezone.
const date1 = new Date('2018-01-19');
const date2 = new Date('2018-01-19 00:00');
const dateString1 = format(date1, 'YYYY-MM-DD'); // gives '2018-01-18'
const dateString2 = format(date2, 'YYYY-MM-DD'); // gives '2018-01-19'
The behaviour is not consistent depending on whether you pass a time or not. If you pass a time then the date object is fixed to the local timezone, but if you don't then it is fixed to UTC. What I would like is that if I pass a datestring without the time (just year, month and day) that it would also create a date object assuming that it would be the start of the day in the local timezone.
Why is this? And do I just have to set the time as 00:00 each time I create a Date object?
"Why is this?"
From the documentation: "Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local."
Parsing dates from strings isn't really advised; the recommendation is to do it manually by splitting the string and using the individual components as parameters. Or use a date library.
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've read this question:
How do you convert a JavaScript date to UTC?
and based on this I implemented this conversion in a dateTools module as follows:
[Update]
var dt, utcTime;
dt = new Date();
utcTime = new Date(Date.UTC(dt.getFullYear(),
dt.getMonth(),
dt.getDate(),
dt.getHours(),
dt.getMinutes(),
dt.getSeconds(),
dt.getMilliseconds()));
Now I'd like to write unit tests. My idea was to check whether the result is actually in UTC, but I don't know how.
All the toString, toUTCString and similar methods seem to be identical for the input (non UTC) and output (UTC) date.
Only the result of the getTime method differs.
Is there a way to check wheter a date is UTC in javascript? If not, is there a better idea to unit test this?
To give more context:
Only converting the it to a UTC string is not that helpful, because in the next step the date is sent to an Asp.net service and therefore converted to a string like:
'/Date([time])/'
with this code
var aspDate = '/Date(' + date.getTime() + ')/';
var aspDate = '/Date(' + date.getTime() + ')/';
This outputs the internal UNIX epoch value (UTC), which represents a timestamp. You can use the various toString methods to get a more verbose string representation of that timestamp:
.toString() uses the users timezone, result is something like "Fri Jan 25 2013 15:20:14 GMT+0100" (for me, at least, you might live in a different timezone)
.toUTCString() uses UTC, and the result will look like "Fri, 25 Jan 2013 14:20:15 GMT"
.toISOString() uses UTC, and formats the datestring according to ISO: "2013-01-25T14:20:20.061Z"
So how do we construct the time value that we want?
new Date() or Date.now() result in the current datetime. No matter what the user's timezone is, the timestamp is just the current moment.
new Date(year, month, …) uses the users timezone for constructing a timestamp from the single values. If you expect this to be the same across your user community, you are screwed. Even when not using time values but only dates it can lead to odd off-by-one errors.
You can use the setYear, setMonth, … and getYear, getMonth … methods to set/get single values on existing dates according to the users timezone. This is appropriate for input from/output to the user.
getTimezoneOffset() allows you to query the timezone that will be used for all these
new Date(timestring) and Date.parse cannot be trusted. If you feed them a string without explicit timezone denotation, the UA can act random. And if you want to feed a string with a proper format, you will be able to find a browser that does not accept it (old IEs, especially).
Date.UTC(year, month, …) allows you to construct a timestamp from values in the UTC timezone. This comes in handy for input/output of UTC strings.
Every get/set method has a UTC equivalent which you can also use for these things.
You can see now that your approach to get the user-timezone values and use them as if they were in UTC must be flawed. It means either dt or utcTime has the wrong value, although using the wrong output method may let it appear correct.
getTimezoneOffset
Syntax: object.getTimezoneOffset( ) This method
returns the difference in minutes between local time and Greenwich
Mean Time. This value is not a constant, as you might think, because
of the practice of using Daylight Saving Time.
i.e.
var myDate = new Date;
var myUTCDate = new Date(myDate - myDate.getTimezoneOffset() * 60000);
alert(myUTCDate);
note: 60000 is the number of milliseconds in a minute;