2

My page was working fine and displaying dates and times as expected until I had to add new Date() to avoid the  deprecation warning. Now my date is 5 hours off what it should be.

enter image description here

How can I fix this? vd and v should both be 12:14:26 and, in this instance, fn should be "Seconds ago".

Here is the full code:

var k = key;
var v = obj[key];
var vd = Date.parse(obj[key]));
if (moment(vd).isValid()) {
    var fn = moment(vd).fromNow();
    v = fn;
}
return {
    name: k,
    value: v
};

I tried the following based on this post, but it brought back the momentjs deprecation warning:

var vd = new Date(Date.parse(obj[key])).toUTCString();

(and still didn't work)

__________________________________________________________________________________

Threaded comments would be cool

What happens if you just run moment(v)? Should work. – Maggie Pint

It does work, but I get the deprecation warning.

I just looked closer. The format of V is ISO8601 with offset, so you shouldn't be getting a deprecation if you just call moment(v). If you are, try moment(v, moment.ISO_8601)Maggie Pint

Again, works, but I still get the deprecation warning.

instead of var vd = new Date(Date.parse(obj[key])).toUTCString(); did you try var vd = new Date(Date.parse(obj[key])).toISOString(); ? or even simplier var vd = Date.parse(obj[key])user3

With .toISOString() it outputs "Invalid Date". var vd = Date.parse(obj[key]) Is what I had originally, it works as expected but I get the warning.

Your v string appears to use ISO8601 format already? Maybe append the Z, or ask moment to recognise it automatically as UTC when timezone info is missing – Bergi

I just tried var vd = new Date(Date.parse(obj[key] + "Z")); and it works!

Community
  • 1
  • 1
  • Like it is explained is the link you provided the problem is that `v` is missing the timezone part, it should be something like "2016-09-14T17:31:40.403Z", you should modify the way you generate `v` to have something more standard – user3 Sep 14 '16 at 17:35
  • Unfortunately I have no control over that. It's how it's stored in the [tag:intersystems-cache] database, as far as I can tell... –  Sep 14 '16 at 17:36
  • 2
    The moment deprecation warning means that you are using the parser incorrectly. The right work around is to specify the correct date format. If you show me your code, I can help you get around that format, and get your code not throwing the warning. – Maggie Pint Sep 14 '16 at 17:47
  • instead of `var vd = new Date(Date.parse(obj[key])).toUTCString();` did you try `var vd = new Date(Date.parse(obj[key])).toISOString();` ? or even simplier `var vd = Date.parse(obj[key])` – user3 Sep 14 '16 at 17:49
  • 1
    I just looked closer. The format of V is ISO8601 with offset, so you shouldn't be getting a deprecation if you just call ``moment(v)``. If you are, try ``moment(v, moment.ISO_8601)`` – Maggie Pint Sep 14 '16 at 17:55
  • Also, why are you re-assigning v to the output of fromNow? Maybe you're then re-using v and that's how you get the deprecation warning? – Maggie Pint Sep 14 '16 at 17:56
  • Your `v` string appears to use ISO8601 format already? Maybe append the `Z`, or ask moment to recognise it automatically as UTC when timezone info is missing – Bergi Sep 14 '16 at 17:56
  • Reusing `v` may be the issue. I have added the full code. –  Sep 14 '16 at 17:58
  • What happens if you just run ``moment(v)``? Should work. – Maggie Pint Sep 14 '16 at 18:02
  • see edits...... –  Sep 14 '16 at 18:07
  • Are you sure you're getting the deprecation warning on the usage of `moment(v, moment.ISO_8601)`? Because that should not throw. You might try adding the "strict" parameter like `moment(v, moment.ISO_8601, true)` or `moment(v, 'YYYY-MM-DDTHH:mm:ss.SSS', true)`. Otherwise, you'll need to check if you're using `moment(something)` somewhere else. – Heretic Monkey Sep 14 '16 at 18:20
  • @MikeMcCaughan At some point I had changed the `if` condition to compare `v` instead of `vd`. My later attempts were in fact throwing the deprecation warning on the condition. Thanks! –  Sep 14 '16 at 18:22
  • So appending `Z` was the solution. `var vd = new Date(Date.parse(obj[key] + "Z"));` –  Sep 14 '16 at 18:23
  • 1
    No need to do that. If the input is UTC, then use `moment.utc` to construct the moment. Don't use the `Date` object if you don't need to. – Matt Johnson-Pint Sep 14 '16 at 18:25

2 Answers2

3

In your example, you're passing a value for v as an ISO8601 string without any offset specified. It is ambiguous as to what point in time you are actually talking about.

Because of changes in the ECMAScript specification, the value will be interpreted as UTC by some browsers, and as local time by others.

The way to avoid this ambiguity is to not use the date constructor. Anywhere you have new Date or Date.parse, you're introducing potential differences in behavior. Just use moment's own parser, and be specific as to your intent.

// your input
var v = "2016-09-14T12:14:26.149";

// pick only one of these:
var m = moment(v);    // input is local time
var m = moment.utc(v) // input is UTC

// then proceed as normal
if (m.isValid()) {
  var fn = m.fromNow();
  // etc.
}

If the input is in some other time zone, or has some other specific fixed offset from UTC, then you have various other options for constructing the moment object. But really, don't rely on the Date object to do the parsing. That's the whole point of the deprecation message.

If the input is not always in the expected format (you're looking for invalid inputs, etc.), then you should specify the expected format such that you don't get the deprecation warning. For example:

var m = moment.utc(v, "YYYY-MM-DD[T]HH:mm:ss.SSS");

This particular format is also available as a constant:

var m = moment.utc(v, moment.ISO_8601);

This, and much more are spelled out in the Moment documentation.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • It will only do that if your input is not in the format you showed. In that case, you'd pass a second parameter containing the tokens describing the format being used. But it's not required for the ISO8601 string that you showed. Verify your input please. Also, make sure you're not on an older version of Moment, in case you're hitting a bug that has since been fixed. – Matt Johnson-Pint Sep 14 '16 at 18:30
  • The [source code for the regex used by Moment](https://github.com/moment/moment/blob/develop/src/lib/create/from-string.js#L9) is illustrative. You could just copy-paste that line, then do `basicIsoRegex.test(obj[key])` and ensure it returns true. – Heretic Monkey Sep 14 '16 at 18:35
  • Soooooo, if you noticed the whole "checking if it's a date" thing, that's because these are dynamic columns and they aren't always a date. I have replaced Moment's `isValid()` with a custom `isDate()` function and it all works now. –  Sep 14 '16 at 18:39
  • Accepting as the answer since yours fixed the problem *when the input was as expected*. –  Sep 14 '16 at 18:40
  • You don't need to do that either. Check out my update. – Matt Johnson-Pint Sep 14 '16 at 19:28
0

It looks like the problem is when you create the date that recovered from the database... because it does not have the timezone... but you know it is "-0500", might be you can add that part hard coded... not ideal but it works

Look at this example:

function getMoment(v){
    var vd = moment(v+"-0500");
  var result = "?";
  if (vd.isValid()){
    result = vd.fromNow();
  }
  return result;
}

Check the getMoment() function, you can just copy and paste and use it in your code.

  • Please include all code in the answer itself, rather than a link to somewhere else. Also, the way you've constructed your URL is incorrect. – Heretic Monkey Sep 14 '16 at 18:32