1

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?

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Excactly what I needed!
Temporal.PlainDate can't get here soon enough! 🙂
2

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.

11 Comments

Right. It must be determined based on application semantics whether a date like that is supposed to mean something relative to the client, or something relative 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...
Basically, all I want on the client side is for the client to be able to pick a date and let the server know about it.
@andreashhp yes but is the date something meaningful for work that the server will do? Or is it something meaningful to the person using the client? If you tell Google to wake you up at 7:00 in the morning, you expect Google to know that you mean 7:00 where you are. If you tell a server "Start a backup at 23:00", you probably mean 23:00 at the server.
Using a "UNIX timestamp" doesn't fix the OP's issue, which is parsing the year, month and day as local then generating a UTC timestamp. The real issue is that ECMAScript doesn't have a date–only form, the closest is YYYY-MM-DD but the TC39 in its wisdom decided to make it UTC, which is inconsistent with ISO 8601.
|
1

See RobG's Answer... using the new Date(Date.UTC(year, month, day)) formatting is much better.

6 Comments

The first suggestion (which requires me to divide .getTimezoneOffset() with 1000) still gives me the same issues... The second suggestion could work, but I do also need the date elsewhere. I could of course do both, but I mean... I can't believe this can't be done properly.
Did you add the 0, and make sure the .getTimezoneOffset was negative - as well? There shouldn't have been a need to divide by 1000...
Ah, I missed the 0,! That actually works. I'll give some time, and if I don't find a better solution, I will accept this! :)
Added an example of a method that builds the expected string first~
No. Because the date represented by the parsed year, month and day may represent a time when the offset is different to the current local offset, e.g. either side of a DST or historic offset change.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.