javascript 在不同的时区开始一天

gwo2fgha  于 2023-02-18  发布在  Java
关注(0)|答案(1)|浏览(160)

我有一个Date。它位于本地时区。我希望新的Date位于一天的开始,位于另一个时区。以下是我不希望看到的内容:

  • UTC格式的Date,相当于转换为UTC的第一个日期
  • 一串

具体来说,UTC不起作用,因为在UTC中获取一天的开始与在时区中获取一天的开始不同。
所以如果我在加尔各答有一个约会,并且想在旧金山得到那一天的开始,加尔各答的日期和格林威治的日期可能不是同一个日期。加尔各答的日期可能是6月15日,格林威治的日期可能是6月15日,但是旧金山的日期可能是6月2日。所以在一个设置为UTC的日期上调用setMinutes(0)等命令是行不通的。
如果有帮助的话,我也使用date-fns(而不是moment),但似乎没有,因为所有日期(包括date-fns-tz中的日期)都以本地时间或UTC时间返回。)
这在Javascript中是可能的还是我疯了?
注:
这与Convert date to another timezone in JavaScript不同
这是关于转换成字符串的。我不想要字符串。

elcex8rz

elcex8rz1#

一种方法是:
1.获取所需位置的当前时区偏移量
1.为所需的UTC日期创建日期
1.应用#1的偏移
例如,使用Get Offset of the other Location in Javascript处的答案:

function getTimezoneOffset(date, loc) {
  let offset;
  ['en','fr'].some(lang => {
    let parts = new Intl.DateTimeFormat(lang, {
      minute: 'numeric',
      timeZone: loc,
      timeZoneName:'short'
    }).formatToParts(date);
    let tzName = parts.filter(part => part.type == 'timeZoneName' && part.value);
    if (/^(GMT|UTC)/.test(tzName[0].value)) {
      offset = tzName[0].value.replace(/GMT|UTC/,'') || '+0';
      return true;
    }
  });
  let sign = offset[0] == '\x2b'? '\x2b' : '\x2d';
  let [h, m] = offset.substring(1).split(':');
  return sign + h.padStart(2, '0') + ':' + (m || '00');
}

// Convert offset string in ±HH:mm to minutes
function offsetToMins(offset) {
  let sign = /^-/.test(offset)? -1 : 1;
  let [h, m] = offset.match(/\d\d/g);
  return sign * (h * 60 + Number(m));
}

// Format date as YYYY-MM-DD at loc
function formatYMD(loc, date) {
  let z = n => ('0'+n).slice(-2);
  let {year, month, day} = new Intl.DateTimeFormat('en',{timeZone: loc})
    .formatToParts(date)
    .reduce((acc, part) => {
      acc[part.type] = part.value;
      return part;
    }, Object.create(null));
  return `${year}-${z(month)}-${z(day)}`
}

// Return stat of day for date at loc
function startOfDayAtLoc(loc, date = new Date()) {
  let offset = getTimezoneOffset(date, loc);
  let offMins  = offsetToMins(offset);
  let d = new Date(+date);
  d.setUTCHours(0, -offMins, 0, 0);
  // If date is + or - original date, adjust
  let oDateTS = formatYMD(loc, date);
  let sodDateTS = formatYMD(loc, d);
  if (sodDateTS > oDateTS) {
    d.setUTCDate(d.getUTCDate() - 1);
  } else if (sodDateTS < oDateTS) {
    d.setUTCDate(d.getUTCDate() + 1);
  }
  return d;
}

// QnD formatter
let f = (loc, d) => d.toLocaleString('en-gb', {
  year: 'numeric',
  month: 'short',
  day: 'numeric',
  hour12:false,
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  timeZone: loc,
  timeZoneName: 'long'
});

// Examples
// 1 June 2020 00:00:00 Z
let d = new Date(Date.UTC(2020, 5, 1));
['America/New_York',
 'Asia/Tokyo',
 'Pacific/Tongatapu',
 'Pacific/Rarotonga'
].forEach(loc => {
  let locD = startOfDayAtLoc(loc, d);
  console.log(loc + ' ' + getTimezoneOffset(d, loc) + 
  '\nZulu : ' + locD.toISOString() +
  '\nLocal: ' + f(loc, locD));
});

// Dates on different date to UTC date
let laDate = new Date('2022-04-30T18:00:00-07:00');
let la = 'America/Los_Angeles';
console.log(`${la} - ${f(la, laDate)}` +
`\nStart of day: ${f(la, startOfDayAtLoc(la, laDate))}`
);
let chaDate = new Date('2022-05-01T03:00:00+10:00');
let cha = 'Pacific/Chatham';
console.log(`${cha} - ${f(cha, chaDate)}` +
`\nStart of day: ${f(cha, startOfDayAtLoc(cha, chaDate))}`
);

但是,我建议您使用支持时区的库,因为Date对象有许多怪癖,而且正在开发一个新的Temporal object

相关问题