【问题标题】:To get time zone offset value based on offset name in luxon根据 luxon 中的偏移名称获取时区偏移值
【发布时间】:2022-02-15 01:04:38
【问题描述】:

对象:

const DateTime = luxon.DateTime;
userInfo = {
   startDate: '14/03/2022',
   startTime: '12:30',
   offsetShort: 'EDT',
 }

从我理解的 luxon 文档中获取 offset value,必须使用这种方法:

DateTime.fromObject(new Date(userInfo.startDate), {zone: 'America/New_York'}).toFormat('ZZ');

会像这样返回偏移值: -05:00

由于我的 api 没有返回区域名称(例如:America/New_York),我想根据偏移短名称(即 IST、EST、EDT)获取偏移值。 luxon 中的任何可能性??

基本上我需要基于偏移短名称(EDT/EST/IST)的以下任何结果:

DateTime.fromObject(new Date('14-03-2022'), {zone: 'EDT'}).toFormat('ZZ'); >> -05:00

 **OR**

DateTime.fromObject(new Date('14-03-2022'), {zone: 'EDT'}).toFormat('ZZ'); >> America/New_York

【问题讨论】:

  • 不,我认为在 luxon 中不可能做到这一点,并且通常不鼓励使用偏移短名称,因为它们模棱两可。请参阅Time zones and offsets#Terminology 声明:命名偏移是偏移的时区特定名称,例如东部夏令时间。 [...] 它们也是模棱两可的 (...)、不标准化和国际化的(法国人会如何称呼美国的 EST?)。由于所有这些原因,在以编程方式指定时间时应避免使用它们。 Luxon 仅支持在格式化中使用它们
  • new Date('14-03-2022') 几乎肯定会产生无效日期,请参阅Why does Date.parse give incorrect results?。如果您使用的是 Luxon,那么也可以使用它来解析时间戳:DateTime.fromFormat('14-03-2022', 'dd-MM-yyyy',{zone:'America/New_York'})
  • America/New_York 推断出美国 EDT 没有的历史性和夏令时变化(美国 EDT 甚至直到 1966 年才存在,并且它的引入和停止日期随时间而变化)。美国 EDT 是 -4,而不是 -5(这是美国东部标准时间)。大多数观察 EDT 的地方也观察 EST(尽管佛罗里达州正试图全年转向观察 EDT)。看,一团糟。 :-)

标签: javascript datetime luxon


【解决方案1】:

为了进一步说明这里的困难,我创建了一个findPossibleIanaZones() 函数。这将需要一个时区缩写,例如ESTEDTIST 并返回匹配的 IANA 时区名称以及当前偏移量(以分钟为单位)。

如您所见,您将获得多个匹配结果,尽管它们通常(但并非总是!)在几分钟内具有相同的偏移量。

我同时使用了 moment-timezoneluxon 来执行此操作,但找不到仅 luxon 的解决方案。

我还创建了一个getOffsetForAbbreviation() 函数,但它不能总是给我们一个明确的结果。

如您所见,IST 可以指代Irish Standard TimeIsrael Standard Time,当然还有India Standard Time

function findPossibleIanaZones(zoneAbbreviation) {
   const timeZones = Object.values(moment.tz._zones).map(z => moment.tz.unpack(z));
   const matchingZones = timeZones.filter(zone => zone.abbrs.includes(zoneAbbreviation));
   return matchingZones.map(z => ({ name: z.name, currentUTCOffsetMinutes: getCurrentOffset(z.name )} )) 
}

function getCurrentOffset(ianaZone) {
    return luxon.IANAZone.create(ianaZone).offset(Date.now());
}

function getUTCOffset(ianaZone, unixTimeMs) {
    return luxon.IANAZone.create(ianaZone).offset(unixTimeMs);
}

function getOffsetForAbbreviation(unixTimeMs, zoneAbbreviation) {
    let zones = findPossibleIanaZones(zoneAbbreviation);
    let offsetNames = zones.map(zone => zone.name);
    let offsets = offsetNames.map(name => getUTCOffset(name, unixTimeMs));
    let uniqueOffsets = [...new Set(offsets)];
    // We should probably throw an error here, null will indicate no value found...
    if (uniqueOffsets.length !== 1) return null;
    return uniqueOffsets[0];
}

const abbrs = ['EDT', 'EST', 'IST'];
for(let abbr of abbrs) { 
    console.log('Timezone abbreviation:', abbr, 'Result:', findPossibleIanaZones(abbr));
    console.log('Current UTC offset:', getOffsetForAbbreviation(Date.now(), abbr));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="https://momentjs.com/downloads/moment-timezone-with-data-10-year-range.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.3.0/luxon.min.js" integrity="sha512-2j5fkjQ4q5ceXgfxi+kqrU2Oz234MrpyywZsQz1F5OGnfat7mOhjRr0oz5cpQ+YwwWB+hhDBSyxNGuL/tKWMFw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

【讨论】:

    猜你喜欢
    • 2020-12-28
    • 2016-05-07
    • 1970-01-01
    • 2020-04-20
    • 2011-02-28
    • 2016-08-06
    • 2021-04-11
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多