Max P
Max P

Reputation: 1459

Make local 24h day from utc timestamp, and convert back to utc

I have utc date 2017-04-22T21:03:54 (local date is 2017-04-23 00:03:54, offset +3)

I would like to get data from server for 1 day. For this example, local day is:

start: 2017-04-23 00:00:00
end: 2017-04-23 23:59:59

And UTC params for server:

start: 2017-04-22 21:00:00
end: 2017-04-23 20:59:59

How I can receive this dates with moment.js? Local offset may be different

I try:

moment.utc(startTime).format() // 2017-04-22T21:03:54Z, but I need 2017-04-22T21:00:00Z
// for example, if local timezone will be +6, I need 2017-04-22T18:00:00Z

Upvotes: 0

Views: 475

Answers (2)

Remus Rusanu
Remus Rusanu

Reputation: 294407

(Putting my comments as answer)

  • The representation of datetimes in a text encoded transport/protocol (as HTTP) should follow ISO-8601. The time portion should include a timezone designator (for UTC time this is the simple Z, see link). These convention removes any ambiguity between client and server about what moment does the time literal represent.
  • Back ends should store times in UTC:
    • This removes any ambiguity when the database moves (failover to standby in different timezone, move of server to new location from east coast to west coats etc).
    • It removes any ambiguity for literals that fall into the DST time overlaps.
    • It removes any ambiguity from rushed legislative changes modifying timezones (of which several occur every few years)

Now that being said, if you need to convert an UTC time to local time in JavaScript/Node with MomentJS, use Moment's local().

Upvotes: 1

RobG
RobG

Reputation: 147453

I have utc date 2017-04-22T21:03:54

A date string without a time zone is treated as local (except for ISO 8601 date-only forms, which ECMAScript treats as UTC, contrary to ISO 8601). If you want to treat a string like "2017-04-22 21:00:00" as UTC then you have to tell the parser (in moment.js you can use the utc method).

You should also always tell the parser the format it's trying to parse, otherwise you're hoping it guesses correctly. If utc is used, moment uses offset +0000 by default (its "UTC mode" * ), not the local offset. If you want the host offset, you can use the local method or convert to a Date object and use built-in methods.

var s = '2017-04-22 21:00:00';
var format = 'YYYY-MM-DD HH:mm:ss';

// Tell parser to treat as UTC and the format
var m = moment.utc(s, format);

// Once the string has been parsed, you can output it in any format you like
console.log(
     'Original format, offset +0000 : ' + m.format(format)
  +'\nBuilt-in toISOString, offset Z: ' + m.toDate().toISOString()
  +'\nBuilt-in toString, host offset: ' + m.toDate().toString()
  +'\nOriginal format, host offset  : ' + m.local().format(format)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

* I'm not sure this is a good idea as it means the code using the object needs to know it's in UTC mode. If you get a moment.js object from elsewhere, it would be good practice to set it to the "mode" you want. Calling local or utc multiple times has no bad effects.

Upvotes: 1

Related Questions