17

As the title stated, I want to get the start time and end time of a day for certain timezone and convert them to utc time. Here is my part of my implementation:

//convert current local time to specified timezone time
var converted = moment.tz(moment(), timezone).format("YYYY-MM-DD");
var full_format = "YYYY-MM-DD HH:mm:ss";

// get start time and end time in the timezone
var start = converted + " 00:00:00";
var end = converted + " 23:59:59";

// how to convert them in utc time by momentjs or other methods? 
var utc_start_time = ?
var utc_end_time = ?

The question is how to convert the time in certain timezone to utc time. Or is there any other decent solutions to it? Thank you!

Edit:

I figured out a way to make it myself which is not quite decent.

var converted = moment.tz(moment(), timezone).format("YYYY-MM-DD");         
var full_format = "YYYY-MM-DD HH:mm:ss";
var start = converted + " 00:00:00";
var end = converted + " 23:59:59";
var utc_start_time = moment(start).add(utc_offset * -1, 'hours').format(full_format);
var utc_end_time = moment(end).add(utc_offset * -1, 'hours').format(full_format); 

Any suggestions on improvements are welcome. Thanks

RobG
  • 142,382
  • 31
  • 172
  • 209
ichbinblau
  • 4,507
  • 5
  • 23
  • 36
  • Possible duplicate of [How do you convert a JavaScript date to UTC?](http://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc) – Genzotto Mar 16 '16 at 09:23
  • are you trying to calculate the gap between them? – Zamboney Mar 16 '16 at 09:27
  • 1
    The questions is not quite identical to [How do you convert a JavaScript date to UTC? ](http://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc). The time to process does not contain any timezone info in it. – ichbinblau Mar 16 '16 at 09:35
  • @Zamboney Nope, just trying to get the utc time of the converted time. – ichbinblau Mar 16 '16 at 09:39
  • is [this](http://momentjs.com/timezone/docs/#/zone-object/parse/) helping? – Zamboney Mar 16 '16 at 09:46
  • @Zamboney, Matt gave the answer I want. But thank you anyway. – ichbinblau Mar 17 '16 at 08:08

3 Answers3

28

Depending on what exactly you want to do:

// for the current day
var start = moment.tz(timezone).startOf('day').utc();
var end = moment.tz(timezone).endOf('day').utc();

// for a specific moment (m)
var start = m.clone().tz(timezone).startOf('day').utc();
var end = m.clone().tz(timezone).endOf('day').utc();

// for a specific calendar date
var m = moment.tz(date, format, timezone);
var start = m.clone().startOf('day').utc();
var end = m.clone().endOf('day').utc();

You can then format start and end however you like with the format function.

Keep in mind also that not every day starts at midnight in every time zone, nor do all local days have 24 hours.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 1
    thanks for the reply again. It did answer my question. I should have read thru the doc before asking. But would you give me an example on in which situation a day does not start at 12am or not have 24 hours. – ichbinblau Mar 17 '16 at 08:05
  • 3
    Any day with a time zone transition, particularly those related to [daylight saving time](http://stackoverflow.com/tags/dst/info) may have more or less than 24 hours by the local clock. Time zones that have a forward-moving transition right at midnight will skip over midnight. Brazil is a good example. Consider that on [October 16, 2016, the day will start at 1:00 in São Paulo, Brazil](http://www.timeanddate.com/time/change/brazil/sao-paulo?year=2016) – Matt Johnson-Pint Mar 17 '16 at 17:14
3

I ran into this problem as well. Unfortunately, moment.js seems to be telling people to use other options. (I guess they are more focused on US politics judging by their website, ugh). Also, many of the momemt funtions in the accepted answer are now depricated. Luxon is the first library that moment suggest as an alternative.

let DateTime = luxon.DateTime;

var dt = DateTime.local() // get the current time in local timezone
  .startOf('day')         // set the time to the start of the current day
  .setZone('GMT');        // change time zone back to GMT (zero offset)
console.log('Start: ' + dt.toISO());  // UTC equivalent for local start of day

var dt = DateTime.local() // get the current time in local timezone
  .endOf('day')           // set the time to the end of the current day
  .setZone('GMT');        // change time zone back to GMT (zero offset)
console.log('End  : ' + dt.toISO());  // UTC equivalent for local end of day (1 ms before midnight)
<script src="https://cdn.jsdelivr.net/npm/luxon@1.22.2/build/global/luxon.min.js"></script>
RobG
  • 142,382
  • 31
  • 172
  • 209
honkskillet
  • 3,007
  • 6
  • 31
  • 47
  • None of the methods in [Matt's answer](https://stackoverflow.com/a/36041365/257182) are currently deprecated. However, according to the [project status page](https://momentjs.com/docs/#/-project-status/), Moment.js as a library is "done" and is in maintenance mode. Given the [Temporal proposal](https://github.com/tc39/proposal-temporal) will supplement (and in practice all but replace) the built–in Date, I suspect that Date will not change for a very, very long time (it hasn't changed significantly in the last 25 years) so moment.js will continue to work for a similar period. :-) – RobG Sep 08 '21 at 05:40
1

Here is a native solution that uses Intl.DateTimeFormat to handle timezones.

It can find the begining/end of the day with specified timezone.

To convert a Date instance to UTC time, use Date.prototype.toISOString.

const beginingOfDay = (options = {}) => {
  const { date = new Date(), timeZone } = options;
  const parts = Intl.DateTimeFormat("en-US", {
    timeZone,
    hourCycle: "h23",
    hour: "numeric",
    minute: "numeric",
    second: "numeric",
  }).formatToParts(date);
  const hour = parseInt(parts.find((i) => i.type === "hour").value);
  const minute = parseInt(parts.find((i) => i.type === "minute").value);
  const second = parseInt(parts.find((i) => i.type === "second").value);
  return new Date(
    1000 *
      Math.floor(
        (date - hour * 3600000 - minute * 60000 - second * 1000) / 1000
      )
  );
};

const endOfDay = (...args) =>
  new Date(beginingOfDay(...args).getTime() + 86399999);

const beginingOfYear = () => {};

console.log(beginingOfDay({ timeZone: "GMT" }));
console.log(endOfDay({ timeZone: "GMT" }));
console.log(beginingOfDay({ timeZone: "Asia/Tokyo" }));
console.log(endOfDay({ timeZone: "Asia/Tokyo" }));
Weihang Jian
  • 7,826
  • 4
  • 44
  • 55
  • In places where daylight saving is observed, this answer will be wrong on the DST changeover days for any time after the changeover time as it applies the wrong offset. The start of the day before the change has a different offset to the rest of the day after the change. – RobG Sep 05 '21 at 04:40
  • Good solution for people who don't want to use moment or any other library.. please add DST logic as and its a perfect answer. – Drunken Daddy Oct 21 '22 at 16:23