3

I have stored a value in an SQLServer DB in UTC which is 2016-07-28 16:00:00.000:

enter image description here

I've converted that UTC DateTime string to an ISO string in Javascript then passed that value into a moment and called toDate() on it.

But the value output is still UTC including the offset.

So I stepped through the results of the two assignments and found the following values at each stage:

1st assignment: (UTC value 4:15 pm form DB converted to ISOString)

var isoDate = new Date('7/28/2016 4:15:00 PM').toISOString(); 

output value: "2016-07-28T15:15:00.000Z"

2nd assignment: (Being output as UTC plus offset instead of expected 17:15 local)

var localOutageStart = moment.utc(isoDate).toDate();

output value:  Thu Jul 28 2016 16:15:00 GMT+0100 (GMT Daylight Time)

Instead I'd like to output the value in local by using the offset, so it would output this value instead in local:

desired output value:  28 07 2016 17:15:00

How can I instead output the local moment time instead of UTC plus offset? I pass the result to a Bootstrap datetime picker which I think takes a moment value.

Brian Var
  • 6,029
  • 25
  • 114
  • 212
  • Your second example already is the local time, not the UTC time. It would also help to know if you are looking for a string, a `Date` object, or a `moment` object in your results, and also what locale and time zone you are using. – Matt Johnson-Pint Jul 30 '16 at 17:35
  • `16:15` is already the local time. The UTC one is `15:15`. Why do you want to sum 1h again? – Oriol Jul 30 '16 at 17:37
  • Also, the *input* in your first example is already in local time as well - so... what are you really trying to accomplish? are you just looking for `.local()` on the moment object? As in, `.utc().local().utc().local()`... you could do this all day long... :) – Matt Johnson-Pint Jul 30 '16 at 17:39
  • @Oriol 16:15 the first value is my UTC value read from the server side. So I'm expecting 17:15 in the local time. Instead it seems to be evaluating 15:15 as the UTC and adding the offset which is incorrect. – Brian Var Jul 30 '16 at 17:48
  • @BrianJ - That part (that the 16:15 is UTC) changes everything. Your first operation treats it as if it were local time. – Matt Johnson-Pint Jul 30 '16 at 17:50
  • @MattJohnson the input in my first example (16:15) is the utc from my server. Local should be 17:15. It seems to be doing the reverse in my example taking the 16:15 subtracting the offset the converting back to UTC. – Brian Var Jul 30 '16 at 17:50
  • @MattJohnson ok my mistake so what operation should I call in the first assignment on the 16:15 UTC value? It seems converting to ISO is incorrect at that point? Also the final output should be a valid js Date or moment. – Brian Var Jul 30 '16 at 17:51
  • See my updated answer – Matt Johnson-Pint Jul 30 '16 at 17:56

1 Answers1

2

If 2016-07-28 16:00:00.000 is in UTC, then you need to treat it as such. As ISO8601, it should be 2016-07-28T16:00:00.000Z. You can get this with moment like so:

var i = "2016-07-28 16:00:00.000";
var s = moment.utc(i).toISOString();

Or without moment, like so:

var i = "2016-07-28 16:00:00.000";
var s = new Date(i + " UTC").toISOString();  // yes, a non-standard hack, but works.

This creates the string: "2016-07-28T16:00:00.000Z"

Then when you want to use it on the client side:

var i = "2016-07-28T16:00:00.000Z";
var m = moment(i);  // here's a moment object you can use with your picker
var d = m.toDate(); // or, if you want a Date object

// or, if you want to custom format a string
var s = m.format("DD MM YYYY HH:mm:ss");

Or if you want to do this with the Date object alone:

var i = "2016-07-28T16:00:00.000Z";
var d = new Date(i);

(But custom formating is more difficult without moment)

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 2
    +1 for the critical part of the browser receiving a string with no timezone, therefore being interpreted as being in the local timezone. – kwah Jul 30 '16 at 18:06
  • Nice I think the main cause of confusion here is what @kwah mentioned that the passed in server date string had no timezone specified. – Brian Var Jul 30 '16 at 18:54
  • I did notice one annoying thing when formatting the moment, it loses minute precision so for example if I read in an ISO string with a value of 4:10 PM after calling .format("MM/DD/YYYY HH:MM"); the minute value of the moment is subtracted by 3. I did post a question on here as haven't seen any similar issue raised before - http://stackoverflow.com/questions/38679715/how-to-resolve-loss-of-minute-precision-formatting-a-moment-in-12hr – Brian Var Jul 31 '16 at 00:29
  • Format tokens are case sensitive. You are using months (`MM`) where you should be using minutes (`mm`), and yes, it's been asked before. – Matt Johnson-Pint Jul 31 '16 at 01:50
  • @kwah—that is completely browser dependent and not to be relied upon. – RobG Aug 01 '16 at 05:03
  • @RobG - I _think_ you're agreeing with me that you should always include the timezone if you want consistent behaviour across browsers? – kwah Aug 01 '16 at 09:31
  • @kwah—nope. ;-) Parsing of strings using the Date constructor is problematic, hence [*this answer*](http://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results/2587398#2587398). – RobG Aug 02 '16 at 04:00