Javascript displaying incorrect date - javascript

Im currently testing out running a server with routes etc. and am trying to display the date of the previous person to request that route. Usually when i use the new Date() object i get it in my local time, but for some reason it is displaying it in UTC (coordinated universal time) and im not sure how to change it.
my code is
var date;
var dateArr = [];
var counter = 0;
router.get('/last.txt', function(req, res) {
counter++;
date = new Date().toString();
dateArr.push(date);
if (counter == 1) {
res.send("");
} else {
res.send(dateArr[counter-1]);
}
});
but i keep receiving the date in the format:
Fri Mar 26 2021 07:24:50 GMT+0000 (Coordinated Universal Time)
Any advice would be appreciated!
EDIT: I live in Australia so i think it usually outputs in AEDT

It would appear that UTC is the timezone in place for the server where this code is running. That's fine, you can convert that to the local timezone on the client quite easily. Rather than using toString, though, I would store either the Date object, or its time value (the result of .valueOf()), or the result of .toISOString() and then send either the time value (a number) or the ISO string value to the client. That way, you're not relying on the timezone of the server. When you pass either of those (the time value or the ISO string) into new Date on the client site, the resulting Date will have the same date/time, but because it's operating in the client's timezone, its local time formatting methods like toString, getFullYear, etc., will use the local timezone of the client.
E.g., change toString to (for instance) toISOString in your code, and on the client:
const dt = new Date(theStringFromTheServer);
console.log(dt.toString()); // Will use the client's timezone to show the date/time

Related

Moment unable to convert in different timezone

My server is returning me dates in UTC and I want to convert them to the timezone of the server (even if the customer browser is in a different timezone !)
Here is one example, my server is in Europe/Berlin.
var dateAsString = '2022-04-11T22:00:00.000Z'; // 2022-04-12 00:00:00 in Europe/Berlin
var utcDate = moment.utc(dateAsString);
console.log(utcDate.format());
var serverTzDate = utcDate.clone().tz('Europe/Berlin');
console.log(serverTzDate.format());
console.log(serverTzDate.format());
var test = moment.utc('2022-04-11T22:00:00.000Z').tz('Europe/Berlin').format();
console.log(test);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.34/moment-timezone-with-data-10-year-range.js"></script>
If my browser is in the Europe/Berlin timezone the output is correct:
2022-04-11T22:00:00Z
2022-04-12T00:00:00+02:00
2022-04-12T00:00:00+02:00
But if I change my timezone (for my example I took Pacific/Niue), then the result is totally wrong, I suppose moment is doing something with the timezone of the browser but how to avoid this ? Here is the output:
2022-04-11T09:00:00Z
2022-04-11T11:00:00+02:00
2022-04-11T11:00:00+02:00
I need to have the date in the timezone of the server and not in the timezone of the browser
With another timezone: Pacific/Kiritimati (-840)
2022-04-12T10:00:00Z // Wanted 2022-04-11T22:00:00Z (UTC Date as entered)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
2022-04-12T12:00:00+02:00 // Wanted 2022-04-12T00:00:00Z (Converted in Europe/Berlin)
Again all the dates are wrong, moment seems not able to parse my date as an UTC date ? It apply the timezone offset of the browser even if I'm using the utc method
moment.utc('2022-04-11T22:00:00.000Z').tz('Europe/Berlin').format()
please check this document. https://momentjs.com/timezone/docs/#/using-timezones/
below is my code result, whatever timezone you changed, the result is '2022-04-12T00:00:00+02:00'

Avoid timezone correction for JavaScript Date

I have a JavaScript function that takes a number (1-31), creates a Date and sends it to a server via an AJAX request:
sendDate(d) {
let date = new Date(this.year, this.month, d);
htmx.ajax("GET", "/some/url", { values: { "date": date.toISOString() } });
}
The problem is, that JavaScript is doing some timezone correction which has the effect, that if I create a date like new Date(2022, 09, 14) I get a date Wed Sep 14 2022 00:00:00 GMT+0200 (Central European Summer Time) which when converted to ISO format becomes 2022-09-13T22:00:00.000Z, ie. the previous day.
I know I can use .toLocaleDateString(), but I would like to stick to the ISO-format and I would also like to avoid hacky solutions such as always creating the date with some specified time at the middle of the day or whatever.
Is there a simple way to create a regular date object and pass it on to a server without timezone shenanigans?
Values passed to the Date constructor are treated as local, toISOString uses UTC. Unfortunately ECMAScript doesn't have a timezone–free, date–only form.
If you want to use toISOString to format the timestamp, then one solution is to parse the values as UTC initially, e.g.
sendDate(d) {
let date = new Date(Date.UTC(this.year, this.month, d));
htmx.ajax("GET", "/some/url", { values: { "date": date.toISOString() } });
}
Example:
let d = new Date()
let year = d.getFullYear();
let month = d.getMonth()
let day = d.getDate();
let date = new Date(Date.UTC(year, month, day))
// Always shows the current local date as 00:00:00Z
console.log( date.toISOString() );
You should also trim the Z from the end since the timestamp really is local.
There’s a way to do that: store the date as the UNIX timestamp. I do it this way and when it’s needed, I pass the timestamp from server to client and convert it into local date.
That said, I don’t think it’s a good idea to build the date on client and pass it to the server, since it could be modified on client. I believe it’s mostly done this way (and that’s also how it’s done in my projects): on the server side, you check the current timestamp (at the time request is sent) and do with it whatever you want.
It appears that you allow your user to pick a date. It would be a good approach to convert it then to timestamp and pass it to the server.
How would you do that? If I return date.getTime() and then parse it (in python) with datetime.fromtimestamp(int(request.GET['date']) / 1000) I still get the same timezone issue...
You won't have any issues in this case - apart from the fact your server just could happen to have a different local time. A time-zone independent solution would have to use utcfromtimestamp instead of fromtimestamp.
Either way, the timestamp itself can't have any timezone problems by definition.
See RobG's Answer... using the new Date(Date.UTC(year, month, day)) formatting is much better.

Preserve Local DateTime in Javascript

My customer's store is in GMT +5:30 timezone but the user's locale is in GMT +8 timezone.
Currently, I'm using javascript's .toISOString() function to convert to UTC and storing UTC in the database. I retrieve UTC from the database and send exactly that the browser, so the new Date('2019-11-15T00:00:00Z') function converts the UTC to the browser's locale.
But, if the user opens a record created by GMT +8 timezone user or vice-versa, the dates are getting messed up.
I'm thinking it would be good if I can transfer the exact date the user enters in the browser and send that exact date to the backend to easily offset using the store's timezone?
The frontend is in VueJs and the backend is in C#.
Always store UTC time in database
Just Store the UTC time in your database, In your client-side, Get client's current timezone,
Here, I am getting IANA timezone from client's system
// get client's timezone (From user's system)
var clientTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
Then, Convert the UTC depends on the timezone and show it to user,
// assume 2019-11-15T00:00:00Z is the UTC date from your database
var convertedTime = new Date('2019-11-15T00:00:00Z').toLocaleString("en-US", {timeZone: clientTimezone});
Example
var clientTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
var timeUtc = '2019-11-15T00:00:00Z';
var convertedTime = new Date(timeUtc).toLocaleString("en-US", {timeZone: clientTimezone});
console.log("Time to Current User : " + convertedTime);
var timeInUsa = new Date(timeUtc).toLocaleString("en-US", {timeZone: "America/New_York"});
console.log("Time in America (New York) : " + timeInUsa);
var timeInAustralia = new Date(timeUtc).toLocaleString("en-US", {timeZone: "Australia/Brisbane"});
console.log("Time in Australia (Brisbane) : " + timeInAustralia);
Note that the js Date object is simply a number that represents an absolute time (independent of any timezone).
So the best encoding/format for transferring and storing a date is that number. IMO this is much simpler than storing a UTC string.
So, on the end-user's machine you would Date.parse the date string provided by the user and this would take account of the user's time zone for you and give you the absolute time number for sending and storing on your backend.
Don't do any formatting or parsing of dates on the backend if you are using Node because there are serious gotcha's and because you shouldn't need to anyway: any client device that needs a date string will do the formatting locally which will automatically convert it to the correct format for their locale and timezone. [edit: the Q did not specify the backend when I wrote this.]
You will need to watch for some gotcha's in the Date.parse function but these are minor compared to the node problems. The most significant IMO is that it will interpret dates in YYYY-MM-DD as ISO 8601 dates (which makes some sense) but then assume that they are GMT if no timezone is specified so you should make sure there is a timezone specified if you use that format.

angular $http.post changing date to UTC date

I was trying to post some data to my REST api which has date.
Now while I debug, my date parameter is a JS Date object with correct date in my timezone: Tue Apr 04 2017 00:00:00 GMT+0530
after it leaves my code, and I see the same in network tab, it is converted to UTC date: "2017-04-03T18:30:00.000Z"
I searched for the solution according to which I need to include locale file of angular in my index.html which I did:
<script type="text/javascript" src="resources/js/angular/angular-locale_en-in.js"></script>
but it doesn't help.
I've seen solutions like adding date format to filter or something, but I want a global solution.
Any help?
Thanks :)
Handling date, time, and timezone have confused me too. May be this answer gives you some insight on how you can handle them.
Try the following code in Chrome's developer console and see how same date is presented in different formats:
var date = new Date();
date.toISOString(); // "2017-04-29T09:54:28.714Z"
date.toGMTString(); //"Sat, 29 Apr 2017 09:54:28 GMT"
date.toLocalString(); //"4/29/2017, 3:24:28 PM"
Any date that you create on client always records the date at zero timezone offset i.e. UTC+/-00:00 Z. For simplicity you may think UTC and GMT as same. When it comes to display purpose the same date is presented as per the browser's timezone. If you do console.log (date) it'll output Sat Apr 29 2017 15:24:28 GMT+0530 (IST) but that doesn't mean that the internal recording of the date is as per browser's timezone. It's just presented on screen/console as per browser's timezone.
Look at date representations not as being converted from one timezone to another but look at them as different representation of the same date. In your browser it is represented as GMT+0530 offset and when it is sent to server it is the same date at zero timezone offset.
As per your comment, if you choose 4th Apr at 00:00 AM in GMT+0530 timezone, internally it'll be 3rd Apr at 18:30 PM in at GMT+0 i.e. zero timezone offset. Let it go to server as it is. When you need to use this date, it comes back from server as 3rd Apr and it'll be displayed in browser as per the browser's timezone offset. There is no conversion involved, it is one date with different representation.
I once asked a related question, may be this adds more clarification.
And overall, this answer is still same as #geminiousgoel and #charlietfl answers.
Scenario :
Send date from UI into API call as an epoch time (UNIX Time) instead of date string. You can use getTime() method to convert the date into epoch time.
var dateStr = "Tue Apr 04 2017 00:00:00 GMT+0530";
var dateEpoch = new Date(dateStr).getTime();
console.log(dateEpoch); // 1491244200000 (Local Time)
At receiver end, they have to convert this epoch time (UNIX time) into Date again.It will give the same local date\time that pass from the UI.
Sample screenshot
Like charlietfl suggested, probably the global hack would be to override Date.prototype.toJSON() method, but that's not a good practice.
Where are you using your $http.post call? The best place to submit an $http request would be in a service. If you use a service, then I suggest you to enwrap your public service API, so that you could have "public" and "private" methods: these could be utilities to perform common operations, such as data transformations, validations..
angular.service('bookStoreService', ['$http'], function($http) {
var normalizeBooks = function(booksArray){
booksArray.forEach(function(book){
// do something on the book
});
};
var updateBooks = function(books){
normalizeBooks(books);
$http.post('myurl', books);
};
return {
updateBooks : updateBooks
};
});
Passing UTC date to server is desired behavior. The client APIs are supposed to handle UTC time instead of assuming the dates are all local dates.
But anyways, you can convert the date to string based on local time zone, and pass the string to server.
i think you just can pass it as string (if the api you use accept strings) with the format you need, let say "Tue Apr 04 2017 00:00:00 GMT+0530" and save it in back-end as string and then when you retrieve it, it will be string and so it will not be changed in any way.
Jindal saab, It will work like this. When we select any date with date picker or just pass any value it takes the original local date but when we pass that value further it converts it into UTC, thereafter it needs to convert to local zone again at receiving end. Database saves date-time in UTC format.
Did you added the angular-locale_en-in.js library to your app? Something like this....
angular.module('myAngularApp', [
'ngLocale'])
Otherwise, the js library won't have any effect in your angular application.
Append UTC at the end so that Browser converts it into UTC date
var dateToServer =new Date(dateFromUser+" UTC");
now the dateToServer will be UTC DateTime format.
Json serializer parse date from string. On a client the date properties are stored as local date in browser time zone. When you are posting your object to server all date properties converts to utc string. In most cases it is a properly behavor. But sometimes you need set and send date in a server time zone. Often it is need when you should set only date whitout time. In that case you should define string propertie and set it manualy. I usaly apply this trick.
class Obj{
d: Date
}
class ObjDto{
constructor(obj: Obj){
this.d= dateTimeToIsoLocalDateString(obj.d)
}
d: string
}
...
export function DateTimeToDate(date) {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
}
export function dateTimeToIsoLocalDateString(dateTime: Date): string {
if (dateTime === null) {
return null;
}
let date = DateTimeToDate(dateTime);
let res = date.toISOString().replace("Z", "");
return res;
}
For more understanding this theme you may learn this topic
//in res data of rest service in x the value is date in y value of y-axis
for (const i in res) {
console.log(i);
const a = {x: new Date(this.mimikatzlog[i].x), y: this.mimikatzlog[i].y};
this.policies.push(a);

json and Utc datetime

I'm storing Utc datetime on the server and requesting data via json to display on client.
The problem is that the server returns the time by its timezone which is different to a client.
How could I get the local dateTime to display on client without hardcoding the offset?
I'm using asp.net mvc and stroring date and time in SQL Server 2008 database as 'datetime'. DateTime format in database is 2013-03-29 08:00:00.000.
You don't say how the UTC time is represented. It's common to use a UNIX time value that is seconds since 1970-01-01T00:00:00Z. If that is what you are using, you can create a date object on the client by multiplying by 1,000 and giving it to the Date constructor:
var unixTimeValue = '1364694508';
var clientDateObject = new Date(unixTimeValue * 1000);
If you are using say .NET, the value may already be in milliseconds so you don't need to multiply by 1,000. You need to check with the source to see what value is passed and what epoch is used if it's a time value.
Javascript date objects are based on a time value that is the same epoch as UNIX, but uses milliseconds. The standard Date methods (getFullYear, getMonth, getDate, etc.) will return values in the local timezone based on system settings. The UTC methods (getUTCFullYear, getUTCMonth, getUTCDate, etc.) return UTC values for the same time.
So if you are passing a time value, use it to create a date object on the client and read the values using standard methods and you have local equivalents of the UTC time value.
If you are passing a datetime string like 2013-03-31T14:32:22Z, you can convert that to a date object using Date.UTC to convert the string to a time value, then give that to the date constructor:
function dateFromUTCString(s) {
s = s.split(/[-T:Z]/ig);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5]));
}
var s = '2013-03-31T14:32:22Z';
alert(dateFromUTCString(s)); // Mon Apr 01 2013 00:32:22 GMT+1000 (EST)
If your input string is a different format, you may need to adjust the split pattern and order of parameters passed to Date.UTC.
Edit
If the string format is 2013-03-29 08:00:00.000 (assuming UTC), you can use:
function dateFromUTCString(s) {
s = s.split(/[\D]/ig);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5], s[6]||0));
}
var s = '2013-03-29 08:00:00.000';
alert(dateFromUTCString(s)); // Fri Mar 29 2013 18:00:00 GMT+1000 (EST)
But be careful of additional spaces. You might want to trim any leading or trailing spaces and ensure there is only one separating the date and time components.
Edit 2
Don't use Date.parse. Until ES5 it was completely implementation dependent. Now it's partially standardised if the string complies with the ISO8601–like format specified by ES5. But that isn't supported by all browsers in use, so not reliable and is otherwise still implementation dependent. The best solution (i.e. one that will work everywhere) is to manually parse the value you are given.
If the format is like: "1364835180000-0700", then you can fairly easily deal with that using a function that subtracts the offset to get UTC time value, the gives that to the date constructor. I'm assuming that -0700 means 7hrs west of Greenwich (javascript timezone offsets have an opposite sense, west of Greenwich is +ve).
Edit 3
Sorry, must have posted the wrong snipped, rushing to a meeting.
// Where s is a time value with offset
function toDate(s) {
// Include factor to convert mins to ms in sign
var sign = s.indexOf('-') > -1? 6e4 : -6e4;
s = s.split(/[\+\-]/);
var l = s[1].length;
// Convert offset in milliseconds
var offset = sign*s[1].substring(l-2,l) + sign*s[1].substring(l-4, l-2)*60;
// Add offset to time value to get UTC and create date object
return new Date(+s[0] + offset);
}
var s = "1364835180000-0700"
alert(toDate(s)); // Tue Apr 02 2013 09:53:00 GMT+1000 (EST)
Return the DateTime as UTC and convert it on the client using .toLocaleString():
#ViewBag.Time = Model.Time.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond
<script>
var time = new Date(#ViewBag.Time);
var localTimeString = time.toLocaleString();
alert(localTimeString);
</script>

Categories