Trouble converting time to UTC for highstocks - javascript

I'm having the hardest time trying to convert this date from an API to UTC milliseconds. As of right now I'm displaying the dates but it's showing 7 hours ahead and going on to the next day which I don't even have data for. Here is the example format:
8/31/2012 9:00:00 AM
I currently have this code
var formattedDate = new Date(data[i].Time);
formattedDate = formattedDate.getTime();
which seems like it's returning the correct value type but the date is wrong. I've also tried
getUTCMilliseconds() and returns 0.
EDIT: jsfiddle example : http://jsfiddle.net/b2NK6/

So you want the raw timestamp in UTC time, instead of local time?
Compare:
(new Date(Date.UTC(2012, 7, 31, 9, 0, 0, 0))).getTime(); /* month 7 is August */
with
(new Date(Date.parse("8/31/2012 9:00:00 AM"))).getTime();
When you parse the string (the second example) it applies your local timezone information when it creates the date object. If you are in timezone -0700, then the date that is created will actually correspond to 4:00pm UTC.
But if you create the date object by explicitly saying that you are specifying the UTC value, it will give you 9:00am UTC, which corresponds to 2:00am in timezone -0700.
Edited to give clearer and more correct code example.

var dateString = "8/31/2012 9:00:00 AM"; // assuming this is expressed in local time
var millisecondsSinceTheEpoch = (new Date(dateString)).valueOf(); // 1346418000000
var isoString = (new Date(millisecondsSinceTheEpoch)).toISOString(); // 2012-08-31T13:00:00.000Z
// Note: example return values from a computer on U.S. Eastern Daylight Time (-4:00).
From W3Schools:
The valueOf() method returns the primitive value of a Date object.
Note: The primitive value is returned as the number of millisecond[s] since midnight January 1, 1970 UTC.
Also see W3Schools for a comprehensive overview of the Date object.

HighStocks expects to get its dates aligned to UTC-midnight date boundary.
Assuming your chart only deals with dates (without the time component) here is a trick you can use:
Do originalDate.getTime() to get the number of milliseconds since midnight UTC 1/1/1970 , e.g. 1362286800000.
Divide the number of milliseconds by (1000*60*60*24) to get the number of days since midnight UTC 1/1/1970 e.g. 15767.208333333334.
Do Math.round() to round the number to the nearest UTC midnight, e.g. 15767.
Multiply the number by (1000*60*60*24) to get it back into the milliseconds scale e.g. 1362268800000.
Here is the final formula:
var utcMidnight=new Date(Math.round(anyZoneMidnight.getTime()/86400000)*86400000)

Related

Is there a way to modify date iso string such that in JS, new Date(isoString) does not return date in daylight saving time

After setting system clock to EST, on converting iso string to date object using Date constructor we noticed that dates between March and November return offset time -4 hrs i.e. daylight saving time and otherwise offset is -5hrs.
For eg, in below screenshot ISO date string is of September month (i.e between March & November) & date returned from new Date() is having offset of -4 (underlined)
And for January month , returned date is having offset of -5 (underlined)
So on calculating the difference in days between the above 2 dates gives the difference in decimal, where the expectation for the difference is that it should be an integer value.
I am calculating the difference using (a.getTime() - b.getTime())/(24*3600000).
Is there a way to modify date iso string such that in javascript, new Date(isoString) does not return date in daylight saving time ?
The automatic change of offset from -5 to -4 & vice versa is causing problems in calculating difference in days in integer and also on adding number of days to a date.
Or is there a better way to handle these issues by an alternate approach? If this can be handled using moment, I'm fine with it.
Please post text, not images.
The strings in the OP are in a format supported by the built–in parser, so should be parsed correctly by modern browsers. As they don't have an offset, they're parsed as local. That results in a time value that is an offset from 1970-01-01T00:00:00Z and is used for the new Date instance.
If the host system is set for a place or region that observes daylight saving at the dates and times represented by the timestamp, it will be used to calculate the time value. If one is during a period of DST and one isn't, then the time difference between them will not be an integer multiple of 24 hours (or 8.64e7 milliseconds).
If you want every day to be 24 hours long, use UTC for everything (including the strings you're parsing). One way is using date–only ISO 8601 strings, such as 2024-09-29. e.g.
let days = (new Date('2024-09-29') - new Date('2023-01-02')) / 8.64e7;
console.log(days); // 636
// or
console.log((Date.UTC(2024,8,29) - Date.UTC(2023,0,2)) / 8.64e7)

convert a string to date object javascript returns an incorrect date

I am trying to convert string to a date object in javascript, however what i day that is minus 1 from day in string. I don't know what is wrong. Here is the method
function formatDate(date_str)
{
console.log(date_str); //input : 2020-03-11
let new_date = new Date(date_str);
console.log(new_date); //output : Tue Mar 10 2020 20:00:00 GMT-0400 (Eastern Daylight Time)
return new_date;
}
The most likely explanation is that parsing the input string "2020-03-11" with no other information equates it to a date of March 11, 2020 at midnight UTC. When you are in a different time zone, then it calculates your time zone offset and gives you a time four hours earlier which would be the day before in local time.
Why such behavior:
The date string(2020-03-11) did not specify any time zone, when you attempt to create a Date object with this string, JavaScript would assume the time zone to be UTC so the date is internally dealt with like as: 2020-03-11T00:00:00Z.
console.log(new_date) would internally call .toString() method on the new_date object and doing that would trigger a date conversion to your local time zone. From the question I believe you(the time on your machine actually) are in GMT-4, this is why 4 hrs is being subtracted from the output of the logs. More details about the date conversion due to time zone here
Possible Fix:
Firstly, we should understand that this is not a bug or an error, it is just how the JavaScript Date object works.
For the scenario described in your question, I'm guessing what you want is to avoid this time zone conversion on the date string. What you can do is add timezone information to the date string before using it to instantiate a date object, with this, javascript wouldn't assume that the date string you are passing into the Date() constructor is in UTC, and when you call Date.toString() or any other similar methods, there won't be any surprises. An implementation for this can be something like this:
// Sorry for the super long function name :)
function add_local_time_zone_to_date_string (date_string) {
// Getting your local time zone
let local_time_zone = (new Date().getTimezoneOffset() * -1) / 60;
// local_time_zone is a number, convert it to a string
local_time_zone = (local_time_zone.toString())
// Padding with 0s if needed to ensure it is of length 2
local_time_zone = local_time_zone.padStart(2, '0');
return `${date_string}T00:00:00+${local_time_zone}`
}
function formatDate(date_str) {
console.log(date_str); //input : 2020-03-11
const date_with_time_zone = add_local_time_zone_to_date_string(date_str);
let new_date = new Date(date_with_time_zone);
console.log(new_date); //output : There should be no surprises here
return new_date;
}

Inconsistency when converting DateTime to JavaScript

I have a ASP.NET webapi with a DateTimeZoneHandling set to Local and I am getting two different results when converting to a JavaScript date.
Example 1
Date returned from server 1932-10-13T00:00:00-04:00
var strDate = new Date("1932-10-13T00:00:00-04:00");
strDate.toISOString(); // 1932-10-13T04:00:00.000Z
strDate.toLocaleString(); // 10/12/1932, 11:00:00 PM
Example 2
Date returned from server 2013-05-09T00:00:00-04:00
var strDate = new Date("2013-05-09T00:00:00-04:00");
strDate.toISOString(); // 2013-05-09T04:00:00.000Z
strDate.toLocaleString(); // 5/9/2013, 12:00:00 AM
I expected behaviour should always be midnight as the dates returned from the server are always midnight. It appears all recent dates parse correctly, however, dates far in the past are incorrect.
The timezone can vary in some locales, for example, I'm UTC-0300, and on certain season shifts it becomes UTC-0200, so it indicates that your locale changed the offset too, making it display the time one hour lesser, basicaly because you locale adopted a different offset along the year.
The example bellow, I've changed your first example to use the same day and month than the second one, so that it proves you that old dates has nothing to do with it.
console.log("Example One");
var strDate = new Date("1932-05-09T00:00:00-04:00");
console.log(strDate.toISOString());
console.log(strDate.toLocaleString());
console.log("--------------------------");
console.log("Example Two");
var strDate2 = new Date("2013-05-09T00:00:00-04:00");
console.log(strDate2.toISOString());
console.log(strDate2.toLocaleString());
Further explanation on UTC/Zulu time
It has normalized the iso date to a zulu date (zero offset iso date). It is still the same datetime, but it has converted the timezone offset into hours making the timezone offset zero.
date [2013-05-09]
separator [T]
time [00:00:00]
offset [-04:00]
The fundamental aspect is that 00:00:00.000-04:00 is the same than 04:00:00.000Z.
If you're simply trying to display the date as someone living in that time would have remembered it (in your case, October 13th happened on October 13th), you may be able to (ab)use Moment Timezone, which appears to format the date as expected:
moment.tz("1932-10-13T00:00:00-04:00", "America/Toronto").tz("UTC").format(); // 1932-10-13T04:00:00Z
In your case, this hacktechnique results in 1932-10-13T04:00:00Z which may be what you are looking for.

JS date calculation with UTC stored on server?

I'm passing back a UTC date from the server, and I need some JS to find the difference in seconds between "now" and the date passed back from the server.
I'm currently trying moment, with something like
var lastUpdatedDate = moment(utcStringFromServer);
var currentDate = moment();
var diff = currentDate - lastUpdatedDate;
problem is, this gives a very invalid answer, because UTC is coming down from the server, and creating a new moment() makes it local. How can I do a calculation with respect to full UTC so it's agnostic of any local timing?
What you aren't quite understanding is that Dates are stored as the number of milliseconds since midnight, Jan 1, 1970 in UTC time. When determining the date/time in the local timezone of the browser, it first works out what the date/time would be in UTC time, then adds/subtracts the local timezone offset.
When you turn a Date back into a number, using +dateVar or dateVar.valueOf() or similar, it is back to the number of milliseconds since 01/01/1970T00:00:00Z.
The nice part about this is that whenever you serialise dates in UTC (either as a number, or as ISO String format), when it gets automatically converted to local time by Javascript's Date object, it is exactly the same point in time as the original value, just represented in local time.
So in your case, when you convert a local date to a number, you get a value of milliseconds in UTC that you are subtracting a value in milliseconds in UTC from. The result will be the number of milliseconds that has passed between the time from the server and the time the new Date() call is made.
Where it gets tricky is when you want a timestamp from the server to not be translated to local time, because you want to show the hours and minutes the same regardless of timezone. But that is not what you need in this case.
Try this way hope it may help:
var lastUpdatedDate = moment(utcStringFromServer);
var date = Date.UTC();
var currentDate = moment(date);
var diff = currentDate - lastUpdatedDate;
I'm assuming that utcStringFromServer is something like this:
Fri, 19 Aug 2016 04:27:27 GMT
If that's the case, you don't really need Moment.js at all. If you pass that string to Date.parse(), it'll return the number of milliseconds since Jan. 1, 1970. You can then use the .toISOString() method to get the same info about right now (converted to UTC) and parse it the same way to get milliseconds since 1970. Then, you can subtract the former from the latter and divide it by 1000 to convert back to seconds.
All in all, it would look something like this:
var lastUpdatedDate = Date.parse(utcStringFromServer);
var currentDate = Date.parse((new Date()).toISOString())
var diff = (currentDate - lastUpdatedDate) / 1000.0; // Convert from milliseconds

JavaScript Date formatting and conversion issue

I'm located in PST timezone and I want to be able to take the string "2014-01-01" and convert it into Unix time without "2014-01-01" getting converted to PST.
Here's what I'm doing:
Date.parse(new Date("2014-01-01"))
I'm getting the value 1388534400000 which is equivalent to Tue Dec 31 2013 16:00:00 GMT-0800 (Pacific Standard Time)
I want to take the date as "2014-01-01" and not convert it into PST before converting it into Unix time.
A few things:
The Date constructor returns a Date object, not a string. You shouldn't wrap it in a call to Date.parse.
If you want a unix timestamp, just call getTime().
var ts = new Date("2014-01-01").getTime();
Alternatively, you can parse the date string without creating a Date object at all.
var ts = Date.parse("2014-01-01");
The behavior of date parsing in JavaScript is implementation dependent. Most browsers will already interpret a yyyy-mm-dd string to be in UTC, due to the dashes (-). If you replace with with slashes (/), you'll see the string get interpreted as local time instead.
I think you're confused about the output. You said the timestamp was equivalent to PST, but that's just one representation. It's also equivalent to the UTC value you passed in. It's not getting converted in the input, it's being converted when you are converting the timestamp back to local time.
You can use a library like moment.js, which gives you full control of the input and output. This is usually the best option, but has the overhead of including a library in your application.
Another way to convert the specified date string to Unix time is as follows:
var str = "2014-01-01";
var parts = str.split('-');
parts[1] -= 1; // js numeric mos are 0-11
var ms = Date.UTC( parts[0], parts[1], parts[2] ); // parts: YYYY, MM, DD
var unix_time = ms/1000; // Unix time uses seconds
console.log("Unix time: " + unix_time);
Date.UTC() returns the number of milliseconds occurring since January 1, 1970 midnight up to the instant of the specified date, irrespective of any timezone. The script transforms the result into Unix time, i.e. seconds, by dividing the number of milliseconds by 1000.
After splitting the string into an array, the code adjusts the element containing the month, lest JavaScript mistake its value for March; JavaScript comprehends numeric months as ranging from 0-11, not 1-12. Next, the script passes the elements sequentially in accordance with the year, month, day parameters that Date.UTC requires. Although UTC() expects numbers for parameters, it accepts the numerical strings.
Note: if you first create a new date object and expect to use a UTC method -- that results in an error because it is a static method of JavaScript's Date Object.
You may check the validity of the UTC() return value, using the aforementioned variables ms and str, as follows:
console.log( new Date( str ).toUTCString( ms ));
The output: Wed, 01 Jan 2014 00:00:00 GMT
See live demo here)
Passing a date string to the Date constructor instead of the numerical parameters it expects affords an unexpected benefit; the date string is treated as if it's timezone is UTC, i.e. zero by the local date object. Once created, the local date object executes its toUTCString() method to attain the above-indicated result. The toString() method would also yield the same output, but it appends local timezone information.

Categories