js, get the local time at midnight for a different timezone

这一生的挚爱 提交于 2019-12-11 15:26:22

问题


I would like to calculate the current local time when it's 24:00 the next day in Los Angeles. The purpose is to set a cookie until the next midnight in la.

I have used moment and moment timezone, however, I can't justify the overhead to the build size for a single function.

Here is what I am working with but I'm stuck on converting the time from LA midnight back to the local time as when i convert back it's before the current time. I don't think there will be an issue with the convertToOtherTimezone function when reversing but I'm not too sure what else to explore.

Any help is greatly appreciated.

const convertToOtherTimezone = (date, from, to) => {
  const utc = date.getTime() + (3600000 * from)
  return new Date(utc + (3600000 * to))
}

console.log(
  'native local time in LA',
  new Date().toLocaleString('en-US', { timeZone: 'America/Los_Angeles' })
)

const LA_OFFSET = -7
// I'm using the AEST timezone -10
const LOCAL_OFFSET = new Date().getTimezoneOffset() / 60

const midnightInLA = (localOffset) => {
  // get the current time in LA
  const la = convertToOtherTimezone(new Date(), localOffset, LA_OFFSET)
  console.log('current time in LA', la)
  // set date to midnight in LA's timezone
  la.setHours(24,0,0,0)
  console.log('next midnight in LA', la)
  // convert back to local time
  return convertToOtherTimezone(la, LA_OFFSET, localOffset)
  // Ulias Hunka gave the correct answer, but deleted his post.
  // reverse the offsets
  return convertToOtherTimezone(la, LA_OFFSET * -1, localOffset * -1)
}

console.log(
  'la midnight in local time',
  midnightInLA(LOCAL_OFFSET)
)
<script src="https://codepen.io/synthet1c/pen/KyQQmL.js"></script>

回答1:


I believe that the snippet in your question is quite close but it appears that you are adding the offset in the wrong direction.

You might encounter problems with daylight savings time - for instance, LA is at UTC-7h during the summer months but UTC-8h normally. If you don't want to use moment.js then the only option I can think of is to parse a locale-formatted string of the time.

This is not the most robust method and will only work (as is) for en-US formatted times. The America/Los_Angeles timezone might also not be available depending on the browser.

let now = new Date()

// Get the current time in LA using string matching to enable the offset to be calculated
// This allows for daylight savings to be considered
// Caution the LocaleTimeString is en-US formatted. Take care if using a different locale
let timeInLA = now.toLocaleTimeString('en-US', { timeZone: 'America/Los_Angeles' })
  .match(/([0-1]?[0-9])\:([0-5]?[0-9])\:[0-5]?[0-9]\s(AM|PM)/)
  // trim first element of match
  .slice(1)
   // take account of AM/PM and convert values to integers
  .map( (e,i,a) => i==0 && a[3] =='PM' ? +e+12 : +e)
  // trim AM/PM
  .slice(0,-1)
  
// positive values mean local time is ahead of LA
let offsets = [now.getHours(),now.getMinutes()].map((e,i) => e-timeInLA[i])

// sum up hours and minutes to get totalOffset and convert to ms
let totalOffsetMS = (offsets[0]*3600 + offsets[1]*60)*1000

// local midnight Tomorrow - add 24 hours and zero other values
let localMidnightTomorrow = new Date(+now.setHours(24,0,0,0))

// LA midnight will happen at the local midnight time with the offset added
let localTimeWhenMidnightInLA = new Date(+localMidnightTomorrow + totalOffsetMS)

console.log(`It will be "${localTimeWhenMidnightInLA.toDateString()} ${localTimeWhenMidnightInLA.toTimeString()}" in your location when it is midnight in LA tomorrow`)



回答2:


Los Angeles standard time is UTC-0800. It changes into daylight saving time (DST) at 2am on the second Sunday in March when the offset changes to UTC-0700. It ends at 2am (DST) on the first Sunday in November.

It is likely that these rules will persist for some time into the future, and if you're only interested in present dates, you can use these rules until they change. You can work out the offset for a given date and time, then create a date for the next midnight in LA. I wish you had put that information in the question and not in comments. See below.

/**
 *  Calculate the offset in LA for the given date and time.
 *  LA DST starts on the second Sunday in March at
 *  10:00 UTC. After that, the offset is UTC-0700
 *  LA DST ends on the first Sunday in November at 09:00
 *  UTC. After that the offset is UTC-0800
 *
 *  @param {Date} date - date object
 *  @returns (boolean} true if DST is being observed
 */
function getLAOffset(date) {
  // Get DST start in UTC
  var start = new Date(Date.UTC(date.getUTCFullYear(), 2, 1, 10));
  start.setUTCDate(start.getUTCDate() + (7-start.getUTCDay())%7 + 7);
  // Get DST end in UTC
  var end = new Date(Date.UTC(date.getUTCFullYear(), 10, 1, 9));
  end.setUTCDate(end.getUTCDate() + (7-end.getUTCDay())%7);
  return (date >= start && date < end)? -7 : -8;
}

/** Return a Date object set to midnight in LA
 *  for the next midnight after the given date.
 *  Offset comes from getLAOffset
 *
 *  @param {Date} date to use for local date values
 *  @returns {Date} set to midnight in LA
 */
function getLAMidnight(date) {
  var d = new Date(+date);
  
  // Get offset. If hour is before offset, set to offset
  // If hour is after offset, set to offset tomorrow
  // Re-check offset and adjust if necessary
  var offset = getLAOffset(d);
  var midLA = d.setUTCHours(-offset, 0, 0, 0);
  if (d < date) d.setUTCDate(d.getUTCDate() + 1);
  d.setUTCHours(-getLAOffset(d));
  return d;
}

// Local date and time for midnight LA tomorrow:
[new Date(2018,0, 1),     //  1 Jan 2018
 new Date(2018,2,11),     // 11 Mar 2018
 new Date(2018,2,11, 12), // 11 Mar 2018, noon
 new Date(2018,2,12),     // 12 Mar 2018
 new Date(2018,5, 1),     //  1 Jun 2018
 new Date(2018,10,4),     //  4 Nov 2018
 new Date(2018,11,1),     //  1 Dec 2018
 new Date()               // Current
].forEach(function(date) {
  console.log('Local date       : ' + date.toString() +
            '\nNext LA midnight : ' + getLAMidnight(date).toString());
});


来源:https://stackoverflow.com/questions/51263321/js-get-the-local-time-at-midnight-for-a-different-timezone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!