1

I'm suffering under the ambiguity of the Date object : local time vs UTC. The problem:

Users can enter the year, month, day, hour, minute that will then be used for a Date object:

const d1 = new Date(y, mo -1, d, h, m)

This creates a new Date for the user input at UTC. Whenever I call d1.toISOString() it returns the ISO string for UTC, not the local, user timezone.

Also, d1.getHours() for instance will be in local time, but with d1.getTimezoneOffset() added to the values. So

d1.getHours() != h
d1.getHours() == h - d1.getTimezoneOffset()

How can this be resolved?

I see the following documentation

Note: Where Date is called as a constructor with more than one argument, the specified arguments represent local time. If UTC is desired, use new Date(Date.UTC(...)) with the same arguments.

But I can not wrap my head around it how to properly use local and UTC times...

My question:

How shall I properly use Date to handle user input and how call the toISOString to get local timestamps? I need the string for the local date as specified by the user in ISO format. Not locale, just the numbers. I do not care about the locale output.

5
  • added a question Commented Dec 13, 2018 at 6:09
  • why do you have a -1 in the parameter to the Date constructor? Additionally, new Date() === new Date(Date.now()) so if you have a Unix timestamp, and call new Date with it it will generate a localized Date Commented Dec 13, 2018 at 6:14
  • 1
    @Meghan Because months are 0 based when passed to the constructor Commented Dec 13, 2018 at 6:14
  • If you want the date as a string in local time, try d1.toLocaleString() Commented Dec 13, 2018 at 6:17
  • I need the string for the local date as specified by the user in ISO format... Commented Dec 13, 2018 at 6:24

1 Answer 1

1

Given:

const d1 = new Date(y, mo -1, d, h, m)

then:

d1.getHours() != h

only in cases where one of the following is true:

  1. h does not exists on that date (e.g. it's in the period of transition from standard to daylight saving time)
  2. h < 0
  3. h > 23.

The following shows that when none of these are true, then d.getHours() == h

let [Y, M, D, h, m, s] = [2018, 0, 1, 15, 30, 15]; // 2018-01-01T15:30:15
var d = new Date(Y, M, D, h, m, s);
console.log(d.getHours() == h);

How shall I properly use Date to handle user input and how call the toISOString to get local timestamps?

Where the Date constructor is called with more than one argument, the values are treated as local. To treat them as UTC, use the Date.UTC method:

`new Date(Date.UTC(Y, M, D, h, m, s)); 

The toISOString method returns a UTC timestamp, always. If you want an ISO 8601 timestamp with a local timezone offset, you should either use a library or write your own function, something like:

function toISOStringLocal(d) {
  // Pad single digit numbers with leading zero
  function z(n){return (n<10?'0':'') + n}
  // Convert timezoneOffset to HH:mm
  function formatOffset(offset) {
    let sign = offset < 0? '+' : '-';
    offset = Math.abs(offset);
    return sign + z(offset/60|0) + ':' + z(offset%60);
  }
  return d.getFullYear() + '-' + z(d.getMonth()+1) + '-' +
         z(d.getDate()) + 'T' + z(d.getHours()) + ':' +
         z(d.getMinutes()) + ':' + z(d.getSeconds()) +
         formatOffset(d.getTimezoneOffset());              
}

console.log(toISOStringLocal(new Date()));

The use of ":" in the offset is required to be consistent with ECMA-262 and should be tolerated by ISO 8601 compliant parsers.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.