Search code examples
javascriptdatemomentjsutcmoment-timezone

How to treat a randomly generated Date as UTC time


Using the moment-random library, I am trying to generate a Date between 2021-02-10 00:00:00 and 2021-02-10 23:59:59 and then create a Date object.

Although I am still trying to understand how this works internally, I think it is using my local timezone prior to creating the Date obj, which results in Date objects being outside of the range I specified.

Example:

let random = momentRandom(
  moment().tz("UTC").format("2021-02-10 23:59:59"),
  moment().tz("UTC").format("2021-02-10 00:00:00")
).format("YYYY-MM-DD HH:mm:ss");
console.log(random);
console.log(new Date(random))

From the code above, I can get the following results (all within the range)

2021-02-10 16:30:38
2021-02-10T21:30:38.000Z
2021-02-10 05:08:59
2021-02-10T10:08:59.000Z

But eventually, if I keep generating Dates, the Date obj may go out of the range based on the value generated randomly.

2021-02-10 21:54:58
2021-02-11T02:54:58.000Z <-- outside the range [2021-02-10 00:00:00, 2021-02-10 23:59:59]

Is there anyway I can use the random value as UTC and let the Date constructor treat that as UTC? Thanks

For example, a desired output:

2021-02-10 05:08:59
2021-02-10T05:08:59.000Z

UPDATE: SOLUTION

I can get the results I am expecting by just appending "Z" to the generated value as such:

console.log(new Date(random + "Z"));

However, I am still wondering what that does and what's happening behind the scenes. A response would still be much appreciated!


Solution

  • moment().tz("UTC").format("2021-02-10 23:59:59") is simply going to return "2021-02-10 23:59:59", always.

    moment() creates a moment for "now", format expects a set of formatting tokens but the above gives it a string containing no tokens, so it just returns the string (which does not contain a timezone offset so is treated as local).

    What you seem to want to do is parse "2021-02-10 23:59:59" as UTC, so use the utc method when parsing the timestamp, not when formatting (because once it's parsed as local, it's too late to change it to UTC):

    console.log( moment.utc('2021-02-10 23:59:59').format() );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

    The default output from format is ISO 8601 so you don't need to provide any tokens and your expression can be:

    let ramdon = momentRandom(
      moment.utc("2021-02-10 23:59:59").format(),
      moment.utc("2021-02-10 00:00:00").format()
    ).format("YYYY-MM-DD HH:mm:ss");
    

    However, that seems a long winded way of changing "2021-02-10 23:59:59" to "2021-02-10T23:59:59Z" when simple string manipulation will have exactly the same result:

    "2021-02-10 23:59:59".replace(' ','T') + 'Z'