0

First thing off, I know how to convert the a local date to UTC in Javascript. This isn't a duplicate of that.

I've been trying to get a function that will convert a date to UTC if it isn't already, I don't have control whether or not the input is UTC or not. I can't use Javascript plugins.

Normal solutions would be just to parse a local date into UTC, but parsing a date that's already UTC that way outputs the weird behavior of modifying the already UTC date incorrectly.

I have an example function below.

function temp() {
  var utc = new Date(Date.UTC(2017, 1, 10, 10, 10, 0));
  var local = new Date(2017, 1, 10, 10, 10, 0);

  var utc2 = new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(),  utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds());
  var local2 = new Date(local.getUTCFullYear(), local.getUTCMonth(), local.getUTCDate(),  local.getUTCHours(), local.getUTCMinutes(), local.getUTCSeconds());

  var utc3 = new Date(utc.getTime() + utc.getTimezoneOffset()*60*1000);
  var local3 = new Date(local.getTime() + local.getTimezoneOffset()*60*1000);

  Logger.log("Timezone offset: UTC=" + utc.getTimezoneOffset() + " Local=" + local.getTimezoneOffset());
  Logger.log("UTC: " + utc.getTime() + " -> UTC2(" + utc2.getTime() + ") or UTC3(" + utc3.getTime() +")");
  Logger.log("Local: " + local.getTime() + " -> UTC2(" + local2.getTime() + ") or UTC3(" + local3.getTime() +")");
}

returns

Timezone offset: UTC=420 Local=420
UTC: 1486721400000 -> UTC2(1486746600000) or UTC3(1486746600000)
Local: 1486746600000 -> UTC2(1486771800000) or UTC3(1486771800000)

Note that even the UTC date has a timezone offset. And that both methods of converting a local date to UTC strangly modifies the already UTC date to something incorrect.

Thank you for your help.

  • When talking about an ECMAScript Date object, the phrase "*I know how to convert the a local date to UTC in Javascript*" doesn't make sense. Javascript Dates are **always** UTC, they can't be "converted to UTC". If you have a string that you wish to parse, that's another story. However, there is no parsing in your question. – RobG Feb 09 '17 at 08:24
  • "*…even the UTC date has a timezone offset*". Dates don't have a timezone offset. The *getTimezoneOffset* method gets the offset from the host system, it has nothing to do with the Date instance. – RobG Feb 09 '17 at 08:26

1 Answers1

1

There is nothing weird about the behavior and unfortunately there is no answer to your question (using the default JavaScript Date implementation).

In JavaScript, each Date is represented by the milliseconds since the epoch. A Date instance is always handled within the interpreters (e.g., your browser's) timezone. Thus, when you call new Date(Date.UTC(2017, 1, 10, 10, 10, 0));, you actually create a Date instance, which is internally represented by 1486721400000.

The getTimezoneOffset() method always returns values from the perspective of your current timezone. So in my case (California), the following:

document.write(new Date(Date.UTC(2017, 1, 8, 10, 0, 0)).toString());
document.write("<br/>");
document.write(new Date(Date.UTC(2016, 8, 8, 10, 0, 0)).toString());

outputs (with comments)

480 // Wed Feb 08 2017 02:00:00 GMT-0800 (PST)
420 // Thu Sep 08 2016 03:00:00 GMT-0700 (PDT)

Trying to find an answer for your question

The only solution I can think of, is that you create your own Date implementation (as you don't want to use any "plug-ins"). You could create your own Date, which can also store the time-zone, or just has a flag which defines if the Date is in UTC. If you reconsider the usage of a JavaScript library, you may want to look at, e.g., https://momentjs.com/timezone/.

Here is a sample on how you could get started with your own implementation

function TzDate (date, utc) {
  if (date instanceof Date) {
    this.date = date;
    this.utc = utc ? true : false;
  } else if (typeof date === 'number') {
    this.date = new Date(date);
    this.utc = true;
  } else if (typeof date === 'boolean') {
    this.date = new Date();
    this.utc = date;
  } else {
    this.date = new Date();
    this.utc = utc ? true : false;
  }
}
 
TzDate.prototype = {
  toString: function() {
    return this.isUTC() ? this.date.toUTCString() : this.date.toString()
  },
  
  getTimezoneOffset: function() {
    return this.isUTC() ? 0 : this.date.getTimezoneOffset();
  },

  isUTC: function() {
    return this.utc;
  }
};

console.log(new TzDate().toString());
console.log(new TzDate(true).toString());
console.log(new TzDate(Date.UTC(2017, 1, 8, 10, 0, 0)).toString());
console.log(new TzDate(new Date(2017, 1, 8, 10, 0, 0)).toString());

see also:

Community
  • 1
  • 1
Philipp
  • 1,289
  • 1
  • 16
  • 37
  • I added a little code snippet, which may help you to get started or get an idea what you could do. – Philipp Feb 09 '17 at 08:12