Luxon:获取偏移量和直到的数组(就像我们可以在时刻时区中一样)

Posted

技术标签:

【中文标题】Luxon:获取偏移量和直到的数组(就像我们可以在时刻时区中一样)【英文标题】:Luxon: get an array of offsets and untils (like we can in moment-timezone) 【发布时间】:2022-01-17 20:08:11 【问题描述】:

使用moment-timezone 库,我目前只是检索特定时区的原始信息,然后直接在我的下游代码中使用。

const zone = moment.tz.zone('Europe/London');

这是一个包含以下内容的对象:


    "name":"Europe/London",
    "abbrs":["GMT","BST","GMT","BST", ...],
    "untils":[-1691964000000,-1680472800000,-1664143200000,-1650146400000, ...],
    "offsets":[0,-60,0,-60,0, ...],
    "population":10000000

offsetsuntils 数组是我真正需要的 moment... 其余的我使用 offsetsuntils 数组在下游代码中“手动”处理自己(或者实际上只是其中的一小部分)...而不必依赖 moment 作为依赖项。

有没有等效的方法来提取luxon 库中的offsetsuntils 数组?

【问题讨论】:

您可以使用IANAZone.create("Europe/London") 获得Zone 对象(请参阅IANAZone.create 的文档),但我担心moment 的offsetsuntils 没有一对一的对应关系。也许你可以使用offset 和其他实例方法来获得你需要的东西。 @VincenzoC 所以也许唯一的方法就是通过循环我感兴趣的时间范围(通常只有几天)来确定untils自己,每个时间增加 1 毫秒时间并传递给offset(),并在offset 中的每次更改时存储until。在实践中,我可以更有效率,因为我知道我的兴趣期最多只有 14 天……如果offset 在开始和结束时是相同的,那么它不会(大概)在两者之间改变。 ..如果开始/结束offset不同,只需要确定确切的转换时间(until)。 @VincenzoC 我发布了一个答案......也许它过于简单......有更好的想法吗? 我没有更好的想法,您的回答对我来说似乎很好,尤其是如果它满足您的需求;) 我主要担心的假设是偏移量只会在小时内发生变化。但话又说回来,在我的用例中,我找到具有毫秒精度的 untils 并不是绝对关键......我没有使用这个控制核电站或发射导弹。 【参考方案1】:

根据@VincenzoC 的评论,这是我试图让offsetsuntils(根据moment-timezone)覆盖给定时间范围的简单尝试。此方法假定偏移量仅在小时内发生变化(因此我们可以将时间范围按一小时递增)。

import  IANAZone  from 'luxon';

const getZoneInfo = function (id, startTime, endTime) 
    startTime = Math.floor(startTime / 36e5) * 36e5; // move to previous whole hour
    endTime = Math.ceil(endTime / 36e5) * 36e5;      // move to next whole hour
    const increment = 36e5;                         // one whole hour
    const zone = IANAZone.create(id);
    const offsets = [];
    const untils = [];
    let offset, prevOffset;
    for (let time = startTime; time <= endTime; time += increment) 
        offset = zone.offset(time);
        if (prevOffset != undefined && offset != prevOffset || time == endTime) 
            offsets.push(-prevOffset);
            untils.push(time);
        
        prevOffset = offset;
    
    const zoneInfo = 
        id: id,
        offsets: offsets,
        untils: untils
    ;
    console.log('zoneInfo', zoneInfo);
    return zoneInfo;
;

const startTime = 1646931245000;
const endTime = 1650473645000;
getZoneInfo('Europe/London', startTime, endTime);
getZoneInfo('Europe/Stockholm', startTime, endTime);
getZoneInfo('Asia/Tokyo', startTime, endTime);
getZoneInfo('America/New_York', startTime, endTime);

输出:

zoneInfo 
  id: 'Europe/London',
  offsets: [ -0, -60 ],
  untils: [ 1648342800000, 1650474000000 ]

zoneInfo 
  id: 'Europe/Stockholm',
  offsets: [ -60, -120 ],
  untils: [ 1648342800000, 1650474000000 ]

zoneInfo 
  id: 'Asia/Tokyo',
  offsets: [ -540 ],
  untils: [ 1650474000000 ]

zoneInfo 
  id: 'America/New_York',
  offsets: [ 300, 240 ],
  untils: [ 1647154800000, 1650474000000 ]

当然,最后的until 并不代表offset 的实际变化,但它的目的是覆盖整个感兴趣的范围(除了endTime 之外不需要任何东西)。

更新

这里是上述的一个变体,它试图通过全天步进来提高效率(特别是对于更大的时间范围),并且只有在偏移量发生变化时才返回以更准确地找到过渡:

import  IANAZone  from 'luxon';

const getZoneInfo = function (id, startTime, endTime) 
    const zone = IANAZone.create(id);
    const offsets = [];
    const untils = [];
    startTime = Math.floor(startTime / 36e5) * 36e5;   // move to previous whole hour
    endTime = Math.ceil(endTime / 36e5) * 36e5;        // move to next whole hour
    const stepSmall = 36e5;                     // one whole hour
    const stepLarge = 24 * 36e5;                // one whole day
    let step = stepLarge;                       // start on the larger step for speed
    let offset, prevOffset, offsetChanged;
    let time = startTime;
    offset = prevOffset = zone.offset(time);
    do 
        time = Math.min(time + step, endTime);
        offset = zone.offset(time);
        offsetChanged = (offset != prevOffset);
        if (offsetChanged || time == endTime) 
            if (offsetChanged && step == stepLarge) 
                // go back a step and switch to using the smaller step to find the transition more accurately...
                time = time - stepLarge;
                step = stepSmall;
                continue;
             else 
                offsets.push(-prevOffset);
                untils.push(time);
                // go back to the larger step...
                step = stepLarge;
            
        
        prevOffset = offset;

     while (time < endTime);

    const zoneInfo = 
        id: id,
        offsets: offsets,
        untils: untils
    ;
    console.log('zoneInfo', zoneInfo);

    return zoneInfo;
;


const startTime = 1608020493000;
const endTime = 1734250893000;
getZoneInfo('Europe/London', startTime, endTime);
getZoneInfo('Europe/Stockholm', startTime, endTime);
getZoneInfo('Asia/Tokyo', startTime, endTime);
getZoneInfo('America/New_York', startTime, endTime);

输出:

zoneInfo 
  id: 'Europe/London',
  offsets: [
    -0, -60, -0, -60,
    -0, -60, -0, -60,
    -0
  ],
  untils: [
    1616893200000,
    1635642000000,
    1648342800000,
    1667091600000,
    1679792400000,
    1698541200000,
    1711846800000,
    1729990800000,
    1734253200000
  ]

zoneInfo 
  id: 'Europe/Stockholm',
  offsets: [
     -60, -120,  -60,
    -120,  -60, -120,
     -60, -120,  -60
  ],
  untils: [
    1616893200000,
    1635642000000,
    1648342800000,
    1667091600000,
    1679792400000,
    1698541200000,
    1711846800000,
    1729990800000,
    1734253200000
  ]

zoneInfo 
  id: 'Asia/Tokyo',
  offsets: [ -540 ],
  untils: [ 1734253200000 ]

zoneInfo 
  id: 'America/New_York',
  offsets: [
    300, 240, 300,
    240, 300, 240,
    300, 240, 300
  ],
  untils: [
    1615705200000,
    1636264800000,
    1647154800000,
    1667714400000,
    1678604400000,
    1699164000000,
    1710054000000,
    1730613600000,
    1734253200000
  ]

【讨论】:

以上是关于Luxon:获取偏移量和直到的数组(就像我们可以在时刻时区中一样)的主要内容,如果未能解决你的问题,请参考以下文章

获取节点中特定时区的 UTC 偏移量和 DST 信息? [复制]

给定元素数组、子列表的偏移量和长度的有效部分缩减

如何在 mongodb 中使用偏移量和限制?

如何从共享库的文本部分获取偏移量和数据?

内存地址,知道dll的偏移量和基地址如何获取内存地址来设置值

Kafka消息的偏移量和顺序消费原理