Converting UTC milliseconds to Central Time in javascript - javascript

We have a bunch of systems events that are stored in a database with a milliseconds timestamp in UTC. In order for me to get the JSON I need, I just need to send a request like this....
http://xxx.xxx.xxx/gimmeJson?starttime=MILLISECONDS&endtime=MILLISECONDS
So when an event happened at 11:00pm CST it has been converted to the UTC millisecond equivalent and stored.
I am having a big issue wrapping my head around milliseconds because I'm thinking about it like timezones.
I saw a SO question similar to this here: How do I convert UTC/ GMT datetime to CST in Javascript? (not local, CST always) and it was close but not quite there.
If timestamps are stored in UTC milliseconds, how can I query them for their Central time equivalent? By that I mean my boss wants a report of all events that happened in the central timezone but I have to query a database that has these timestamps stored as UTC milliseconds.
Ultimately I have to come up with ** some ** number to send on a URL for UTC MILLISECONDS that is the equivalent of say "September 24, 12:00:00 Central". What compounds this issue is that the web service is fairly new and has been shown to be a bit buggy so I need to make sure I have this right.
// construct a moment object with Central time input
var m = moment('2015-01-01 00:00:00').format('x');
// convert using the TZDB identifier for GMT
m.tz('Europe/London');
// format output however you desire
var s = m.format("x");
Can someone confirm I am on the right track?
Many, many thanks in advance.

There's no such thing as milliseconds timestamp in UTC or any other timezone. Millisecond timestamps are always from 1970-01-01T00:00:00.000Z; they are zone agnostic.
In order to get the timestamp for the zone you want, simple create a Date instance and use the Date.prototype.getTime method
var cstTime = new Date('2016-09-24T12:00:00-06:00');
console.log('CST in ISO 8601:', cstTime.toISOString());
console.log('CST timestamp:', cstTime.getTime());
var localTime = new Date();
console.log('Local time in ISO 8601:', localTime.toISOString());
console.log('Local timestamp:', localTime.getTime());

Related

convert date based on timezone user is in

I have a date I want to convert based on their timezone.
For example, I want to set it in EST time (America/New_York)
2019-04-24 12:00:00
and if the user comes across the site from America/Los_Angeles, it will appear:
2019-04-24 09:00:00
I need to be able to return the hour, so in that example: 9.
I tried using https://github.com/iansinnott/jstz to determine their timezone and https://moment.github.io/luxon in hopes of handling the conversion w/o any luck.
I was testing by changing the timezone on my computer w/o any luck.
It sounds like you're asking to convert from a specific time zone to the user's local time zone (whatever it may be). You do not need time zone detection for that, but at present you do need a library. (Answers that suggest using toLocaleString with a time zone parameter are incorrect, as that function converts to a specific time zone, but cannot go the other direction.)
Since you mentioned Luxon, I'll provide a Luxon specific answer:
luxon.DateTime.fromFormat('2019-04-24 12:00:00', // the input string
'yyyy-MM-dd HH:mm:ss', // the format of the input string
{ zone: 'America/New_York'}) // the time zone of the input
.toLocal() // convert to the user's local time
.toFormat('yyyy-MM-dd HH:mm:ss') // return a string in the same format
//=> "2019-04-24 09:00:00"
This capability is also provided by other libraries, such as date-fns-timezone, js-Joda, or Moment-Timezone, but it is not yet something built in to JavaScript.
Converting date based on the time can be done like this. reference convert date to another time zone example snippet is under.
var usaTime = new Date().toLocaleString("en-US", {timeZone: "America/New_York"});
usaTime = new Date(usaTime);
console.log('USA time: '+usaTime.toLocaleString())
var usaTime = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});
usaTime = new Date(usaTime);
console.log('USA time: '+usaTime.toLocaleString())
You could keep a list of timzeone identifiers and a list of their corresponding +/- number of hours with respect to your local time (which is returned by your time function).
Once you have a user's time zone, and you have extracted the current hour from the local timestamp simply look up the timezone in your list and use it's index to access the second list to find how many hours to add or subtract from the users time.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
var date = new Date(Date.UTC(2012, 11, 12, 3, 0, 0));
// toLocaleString() without arguments depends on the implementation,
// the default locale, and the default time zone
console.log(date.toLocaleString());
// → "12/11/2012, 7:00:00 PM" if run in en-US locale with time zone America/Los_Angeles
Or you can use getYear, getMonth, getDate, getHours, getMinutes, getSeconds to format your own representation of the date. These methods all return values according to the user's local timezone.
I think the question may need more clarification - my first impression was you refer to a date-time that you already have and serve from the server. Doesn't this problem boil down to the Date object being "user-timezone-aware"? or not? But it is (some methods are, to be exact)
Your date/time is 2019-04-24 12:00:00 EDT (i assume P.M.)
This means the Unix timestamp of this in milliseconds is 1556121600000
(i assume daylight is on for April so not pure EST but EDT and an offset of UTC-4:00)
When you call
console.log(new Date(1556121600000).getHours())
doesn't this return 9 as you suggest, for Javascript executed on a browser from America/Los_Angeles with PDT timezone?
As suggested at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getHours :
The getHours() method returns the hour for the specified date,
according to local time.

How to save correct time in database?

I have one object called appointment which has two properties: StartDate and EndDate.
When I make POST request I send these values using ISOString time .
this.appointment.StartDate.toISOString()
On the server-side, I received these properties with correct values. Also, it seems to be correct when I create model in order to save appointment to the database. I used .ToUniversalTime() method.
var newAppointment = new Appointment()
{
StartDate =Convert.ToDateTime(model.StartDate).ToUniversalTime(),
EndDate = Convert.ToDateTime(model.EndDate).ToUniversalTime(),
SpecialityId = speciality.Id,
LocationId = location.Id,
PatientId = patient.Id,
UserId = user.Id,
Observations = model.Observations
};
But in database I found another values. Can explain somebody why is this behaviour ?
For instance, I used 2017.09.01 11:00 for StartDate and in database i found 2017-09-01 08:00
The server and database is located in the westeurope.
A few things:
Don't call ToUniversalTime in a web application. It's designed to convert from the server's local time zone to UTC. The server's time zone should be irrelavent to your application. Web applications should never use ToUniversalTime, ToLocalTime, DateTime.Now, TimeZoneInfo.Local, DateTimeKind.Local or any other method that uses the time zone of the computer it's running on.
Ideally, on the server side, your model.StartDate and model.EndDate would already be DateTime objects, because they'd have been deserialized that way. Therefore, you probably don't need to call Convert.ToDateTime. If they are strings, then I would adjust your model class accordingly.
On the client side, assuming StartDate and EndDate are JavaScript Date objects, and they were created using local time values (that is, the time zone of the browser), when you call toISOString, you're not just getting a string in ISO 8601 format - it is also converting it from the browser's time zone to UTC.
In your example, the UTC time is 3 hours ahead of UTC for the date and time shown. From your profile, I see you are located in Romania, which is indeed UTC+3 for this date, because it is currently observing Eastern European Summer Time. When Summer Time ends (on October 29, 2017 at 04:00), it will return to UTC+2. For this reason, you cannot simply add three hours to all values.
If you want to send local time values from the client, you should send them in ISO 8601 format, without any Z or offset, for example 2017-09-01T11:00. There are several ways to achieve this:
The best way is to not have them in a Date object to begin with. For example, if your input uses the <input type="datetime-local" /> input type (as specified in HTML5), the .value property is not a Date object, but rather a string in ISO 8601 format.
If you can't avoid a Date object, then create a local ISO string, like this:
function dateToLocalISOString(date) {
var offset = date.getTimezoneOffset();
var shifted = new Date(date - offset * 60 * 1000);
return shifted.toISOString().slice(0, -1);
}
OR, using Moment.js:
moment(yourDateObject).format("YYYY-MM-DD[T]HH:mm:ss.SSS")
Lastly, you will probably read advice from others about storing these as UTC. Don't listen. The advice "always use UTC" is shortsighted. Many scenarios require local time. Scheduling appointments is a primary use case for local time. However, if you need to act on that appointment, you'll use the current UTC time, and you'll also need some information about the time zone for the appointment so you can convert from UTC to the appointment's time zone. For example, if this is something like an in-person doctor's office appointment, then it's safe to assume the time zone of the doctor's office. But if it's an appointment for an online meeting, then you'll have to capture the user's time zone separately and apply it on the back end where appropriate.
The problem is with your current timezone.
What your application does is get current timezone (+3) in this case.
Now it got your timezone but it will convert to utc time. So what will happen, your current time will be -3 hours.
If you not adjust to summer and winter time then you can simply add 3 hours to the datetime. Otherwise you have to get the offset of your timezone and add that to the current datetime value.
Take care if you use this application in different timezones. For example You life in +3 and some else life in +2 timezone.

Moment.js local relative time

I have dates in my database set to Europe/London time. I am using Moment.js to show relative time e.g. "3 minutes ago". This works fine for me as I am in the same timezone, but for example, someone who is PST timezone would see "in 8 hours". How can I fix this?
My current code is like this:
$('time').text( moment( '2016-01-22 18:00:00' ).fromNow() );
To echo Jon's answer, moment's relative time functionality is strictly UTC based, so the behavior you describe won't actually happen, unless you are interpreting the original timestamp in local time.
It's hard to say if you're doing that or not, as you didn't give a sample value of the input string.
If your times are indeed UTC based, but that's not reflected in the input string, then use moment.utc instead of just moment.
And no, London is not the same as UTC.
I believe that the best approach is to store the date in UTC and then convert this to the local time zone for display. Note that this is not necessarily the same as London time because UTC does away with daylight savings time nonsense. You can do everything that you need with the date class provided the time stamp stored in the database does not have to deal with the vagaries of time zone and DST. The date class maintains its own epoch internally as milliseconds elapsed since midnight 1 January 1970 UTC. You can evaluate the difference between two Date objects as follows:
var agora = Date.now();
var stored = ... // the date that was stored in your database
var diff_msec = agora.getTime() - stored.getTime();
Knowing that the difference and that its units are milliseconds, you can convert the difference to whatever units are best for presentation.

Javascript countdown using absolute timezone?

I have a javascript countdown timer that works by taking a specified date and time, and comparing it to the current date and time. The issue is, the current time is relative to the users timezone, so the time remaining is different between users.
How can I have the timer countdown till a time in a specific timezone, in my case GMT -5 hours?
I understand i can use the below code to get the users timezone, but I am lost as how to use this.
myDateObj.getTimezoneOffset( ) / 60
You can use Date.UTC(year,month,day,hours,minutes,seconds,msec)
It operates just like the Date constructor, but returns the timestamp of the arguments at Greenwich time (offset=0) instead of local time.
var localtime=new Date(Date.UTC(year,month,day,hours,minutes,seconds,msec))
returns the local time for the UTC time specified.
Everyone (whose clock is set correctly) will end the countdown together.
A quick search reveals: convert-the-local-time-to-another-time-zone-with-this-javascript
Following the article verbatim gets you this example:
var d = new Date();
var localTime = d.getTime();
var localOffset = d.getTimezoneOffset() * 60000;
var utc = localTime + localOffset;
// obtain and add destination's UTC time offset
// for example, Bombay
// which is UTC + 5.5 hours
var offset = 5.5;
var bombay = utc + (3600000*offset);
var nd = new Date(bombay);
alert("Bombay time is " + nd.toLocaleString() + "<br>");
jsFiddle: http://jsfiddle.net/GEpaH/
Just update with your desired offset and you should be all set.
Just create a Date with an RFC 2822-timestamp with timezone. That time will then be converted to the users current location (based on OS settings). Even with corrections for daylight savings time!
I'm in Norway, which currently is in daylight savings time, so it's GMT+2. Here is what happens when I create a Date object using GMT-0500:
var myDateObj = new Date("Fri Apr 17 2015 12:00:00 GMT-0500 (CDT)");
myDateObj.toString();
Fri Apr 17 2015 19:00:00 GMT+0200 (CEST)
How to get the correct date string for your location? If it's the timezone you're currently in; just do myDateObj.toString() in your browsers dev-tools console. For a different timezone; change the timezone in your operating system first. (Or read the RFC)
new Date().toString();
Fri Apr 17 2015 12:36:57 GMT+0200 (CEST)
You don't really say exactly what your are trying to accomplish. The javascript date object retrieves the local time and the "timezone offset" (relative to GMT (UTC)). These are of course "set" by the user so even if in the same time zone, two users are very unlikely to have the same "time".
If you are trying to time between different users you need to be referencing some centralized time authority.
I would use an AJAX type call (XMLHttpRequest) to a page own my own server that returns my server's time. That way each user is referencing the same time.
Google XMLHttpRequest to find examples of the JS code you need (and oftentimes the corresponding server-side code for a simple service such as this).
PS: I would also install some simple client software to keep the time on my server accurate by synching with an atomic clock every 10 minutes.
You can't get an accurate date with JavaScript as it is client-side and it is based on the user's operating system clock. You can use jCounter to display countdowns based on server-side timezones.
But hey, if you really want to do it yourself, download jCounter and you'll find a dateandtime.php file as well which retrieves the current date server-side, as timestamp (it will have to be placed on a server btw, not on your desktop :P)
Check how that script uses that file and retrieves the real current date to operate against it and calculate accurate countdowns.
Cheers
To revise the approach Brandon has taken to calculate a UTC-shifted time, we can slim the code down into a two-line extension of the Date object:
/* getOffsetDate - Returns a Date shifted by a certain offset
* #param offset the UTC offset to shift, in hours
* #return new date object shifted by UTC offset
*/
Date.prototype.getOffsetDate = function( offset ) {
utc = this.getTime() + (this.getTimezoneOffset() * 60000);
return new Date(utc + (3600000*offset));
}
You can then calculate the UTC-5 shifted date as follows:
myDate = new Date().getOffsetDate(-5);
It should be noted that extending native prototypes in this manner is generally considered a bad practice since it muddles core objects that other libraries depend upon. To justify it, you'd have to argue this functionality should be a native part of the Date object.

What format is this timestamp, and how can I format it in its own time

I have a problem converting a timestamp in javascript.
I have this timestamp:
2011-10-26T12:00:00-04:00
I have been trying to format it to be readable. So far, it converts this using the local time of my system instead of the GMT offset in the timestamp. I know the timezone that this was created in is EST. I'm in PST, so the times are being offset by 3 hours.
Instead of this showing as:
Wednesday October 26, 2011 12:00 pm
It shows as:
Wednesday October 26, 2011 9:00 am
I have tried a few different solutions, but the latest one is found here: http://blog.stevenlevithan.com/archives/date-time-format
I am less concerned with the formatting part as I am with figuring out how to handle the GMT offsets. Would appreciate any help and insight anyone can provide.
Date objects are created in the local zone. If the date string was created in a different time zone, then you need to adjust the date object to allow for the difference.
The abbreviations PST and EST are ambiguous on the web, there is no standard for time zone abbreviations and some represent two or zones. You should express your zone only in terms of +/- UTC or GMT (which are the same thing, more or less).
You can get the local time zone offset using Date.prototype.getTimezoneOffset, which returns the offset in minutes that must be added to a local time to get UTC. Calculate the offset for where the time string was created and apply it to the created date object (simply add or subtract the difference in minutes as appropriate).
If your time zone is -3hrs, getTimezoneOffset will return +180 for a date object created in that zone. If the string is from a zone -4hrs, its offset is +240. So you can do:
var localDate = new Date('2011-10-26T12:00:00') // date from string;
var originOffset = 240;
var localOffset = localDate.getTimezoneOffset();
localDate.setMinutes( localDate.getMinutes() + originOffset - localOffset );
Adding the origin offset sets it to UTC, subracting the local offset sets it to local time.
It would be much easier if the time string that was sent by the server was in UTC, that way you just apply the local offset.
Edit
IE will not parse a time string with an offset, and Chrome thinks that the above time string is UTC and adjusts for local offset. So don't let Date parse the string, do it manually.
It doesn't matter what time zone you are- the time stamp will result in a different local time for every different time-zone, but they all will be correct, and anyone checking the UTC time of the date will get the same time-stamp:
new Date('2011-10-26T12:00:00-04:00').toUTCString()
returns
Wed, 26 Oct 2011 16:00:00 GMT
and getTime() anywhere returns the same milliseconds universal timestamp:1319644800000

Categories