1

Backstory I've been beating my head for a week trying to simply store and resume scheduling dates in JS. To save dates between sessions I need to use Stringify to offload a single string to be saved as a variable. I am programming JS in a custom engine (Barco's Medialon) that does not allow includes or standard I/O. So everything has to work in this one block of code with small things not being standard or needing workarounds.

The problem This JSON stringify command stores date objects in a standard format "2019-03-05T09:20:00.000Z" This particular JSON parsing//new Date() command, however, can not interpret that string format and creates an error of "Invalid Date". Other formats do work though, IE when I invoke a new Date(Epoch Time) or new Date(YYYY,MM,DD,hh,mm)

The Quest I am trying to modify the stringify/parse sections to work around this issue though I am struggling. While I have a small handle on the 'JSON.parse' and regex bit, Trying to manipulate the detection of Date Object and changing how it encodes is a quest in futility thus far.

Object structure getting Stringified

{
  "daily": "",
  "special": [
    {
      "startDTG": "2019-03-05T09:20:00.000Z", // <- Without modifying the default stringify it gives this
      "endDTG": "2019-03-06T09:20:00.000Z",
      "mode": "0"
    }
  ],
  "current": {},
  "startup": [],
  "shutdown": []
}

I have tried the following strigify manipulation:

        var currentEvents = JSON.stringify(this.Events, function(key,value) {
            if (value instanceof Date){             
                    return value.getTime();         
            }
            return value;
        });

The above however, does not detect the Date Object. If I use (typeof value === 'object') it activates on far too much.

On the other side, here is the non-working for this engine (but works everywhere else!) code

eventLoad = JSON.parse(eventSTR, function (key, value) {
            var reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
                if (typeof value === 'string' && reISO.test(value)){                
                    return new Date(value);  //value.slice(0,-5));              
            }
            return value;
        });

The goal I need to find a solution to work around the limitations of this engine that allows me to detect and convert a Date to a string during the JSON.stringify process in an alternate form that also allows the JSON.Parse function to detect and import it back as a Date object

Antony T.
  • 15
  • 7
  • TLDR What exactly is the question? See [ask] – geoidesic Feb 07 '19 at 20:58
  • *"here is the non-working for this engine..."*: what exactly happens? Is it the regex that does not work? Is it the `test` method that fails? Is it `new Date` that misinterprets the argument? If so, how? Is there an exception? – trincot Feb 07 '19 at 20:59
  • @trincot The failure itself is when ``` new Date("2019-03-06T09:20:00.000Z"); ``` is invoked. The result is a malformed Date object in which no get functions work. The debugger provided by this engine does not complain other than stating "Invalid Date" . and when I typecast the Date object to a string, I only get the same "Invalid Date" @geoidesic I have re-written the goal portion with a clearer question. – Antony T. Feb 07 '19 at 21:12
  • *"This however, does not detect the string. "*: I don't understand this part. Does your original object not contain `Date` objects? Why should it detect (other) strings? – trincot Feb 07 '19 at 21:29
  • @trincot I fixed the wordage, that was a brain fart on my behalf, It was not detecting the Date Objects. – Antony T. Feb 07 '19 at 21:51

2 Answers2

0

In the JSON.parse callback, you could call Date.UTC with 7 arguments, and pass the resulting epoch value to the Date constructor, like so:

var p = value.match(/\d+/g);
return new Date(Date.UTC(p[0],p[1]-1,p[2],p[3],p[4],p[5],p[6]));

This assumes that the stringified date uses the UTC format with the "Z" timezone indication. This is what JSON.stringify produces for dates.

Demo:

var event = {
    dt: new Date()
};
console.log("input:");
console.log(event);
var eventSTR = JSON.stringify(event);
console.log("stringified:");
console.log(eventSTR);
var reISO = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d+Z$/;
var result = JSON.parse(eventSTR, function (key, value) {
    if (typeof value === 'string' && reISO.test(value)) {
        var p = value.match(/\d+/g);
        return new Date(Date.UTC(p[0],p[1]-1,p[2],p[3],p[4],p[5],p[6]));
    }
    return value;
});
console.log("parsed:");
console.log(result);

Concerning the stringify solution

If instanceof Date does not work, then you could test the presence of a Date prototype method:

if (Object(value).getTime) {
    return value.getTime();
}

However, in the parsing phase you would have trouble to distinguish such epoch numbers from other numerical values; you would have no good indication whether the number should be converted to a Date...

trincot
  • 317,000
  • 35
  • 244
  • 286
  • This answer works! I had to compensate for different formats IE 0-11 for month vs 1-12 for month. Thank you tenfold! – Antony T. Feb 08 '19 at 00:11
  • @Anthony—`p[1]` should be `p[1] - 1` for all. It's an ECMAScript thing, not specific to IE. – RobG Feb 08 '19 at 01:27
  • Can you update the answer to fix the month index? You can't use spread like that as the month still needs to be decremented. :-) – RobG Feb 08 '19 at 01:32
  • Thanks for the comment about the month. Corrected. – trincot Feb 08 '19 at 08:21
-2

You're trying to do it all manually but there are already methods for handling all of these conversions.

Date to ISO: https://www.w3schools.com/jsref/jsref_toisostring.asp

ISO to Date: Convert ISO Date to Date Format yyyy-mm-dd format in javascript

And specifically for the :00.000Z format see this answer: What does this format means T00:00:00.000Z?

Moment.js is also a great time-saver for this sort of thing: http://momentjs.com/

geoidesic
  • 4,649
  • 3
  • 39
  • 59