从 UTC 偏移量获取所有可能的时区

问题描述 投票:0回答:3

我有以下价值-

GMT -0800

如何获取共享此偏移量的所有时区的列表?

javascript node.js datetime momentjs
3个回答
1
投票

这是按偏移量列出时区的示例,值得指出的是,由于许多区域的夏令时,给定时区的 UTC 偏移量会发生变化。

<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.slim.js"></script>
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data-2012-2022.js"></script>

<script>


function initialise() {

    $("#offsetSelector").on('change', function (event) {
       showTimeZones();
    });

    var startOffset = -12;
    var offsets = Array.from(Array(48).keys()).reduce((acc, val) => {
        acc.push(startOffset);
        startOffset += 0.5;
        return acc;
    }, []);

    offsets.forEach((offset) => {
        var selector = document.getElementById("offsetSelector");
        var el = document.createElement("option");
        el.textContent = offset;
        el.value = offset;
        selector.appendChild(el);
    });

    document.getElementById("offsetSelector").value = -8;
    showTimeZones();
}

function showTimeZones() {

    var utcOffset = $('#offsetSelector').val();
    var timeZones = moment.tz.names();

    var result = timeZones.filter((zone) => {
        var tz = moment.tz.zone(zone);
        /* We'll make the assumption we're looking for the offset outside of DST */
        var currentOffset = tz.utcOffset(new Date('2018-01-01'));
        return  (currentOffset === (-utcOffset*60));
    });

    $("#list").empty();
    console.log('Zones:');
    result.forEach((zoneName) => {
      console.log(zoneName);
      var ul = document.getElementById("list");
      var li = document.createElement("li");
      li.innerHTML = zoneName;
     // li.appendChild(document.createTextNode(zoneName));
      ul.appendChild(li);
    });
}

</script>

</head>
<body onLoad = "initialise()">
<b>Offset (hours):</b>
<select id="offsetSelector">
</select> 

<br/><br/><b>TimeZone list:</b><br/>
<ul id="list"></ul>
</body>
</html>

JSFiddle: https://jsfiddle.net/p9h5wgcr/


1
投票

我将分两部分回答这个问题:

1)查找包含时区名称及其偏移量的数据集

您可以手动编译此数据集(也许使用维基百科的数据),或者 NPM 包 timezones.json 似乎也合适。

2)搜索列表

给定两个输入:初始时区和偏移量(例如

GMT
-8
),您需要:

  1. 在数据集中搜索初始时区的偏移量(例如

    GMT
    +0

  2. 将两个值相加,例如

    GMT-8
    =>
    0 - 8 = -8

  3. 过滤数据集以查找偏移量为

    -8

  4. 的值

示例:

假设您在变量中拥有上面 NPM 包中

timezones.json
的内容
timezones_file

const timezones = JSON.parse(timezones_file);

// Step 1 above
function findOffset(timezone) {
   const matches = timezones.filter( zone => zone.abbr === timezone );
   return matches ? matches[0].offset : null;
}

// Step 2 above
function findByOffset(offset) {
    return timezones.filter( zone => zone.offset === offset );
}

// Answer to your question, accepts a timezone (e.g. 'GMT') and offset (e.g. -8)
function getListOfTimezones(initial_timezone, initial_offset) {
    const new_offset = findOffset(initial_timezone) + initial_offset;
    return findByOffset(new_offset);
}

0
投票

要完成此任务,您可以使用以下 Vanilla JS 函数:

// Return an object with timezones in keys and UTC offset in value.

function get_all_timezones_offsets(date = null) {
    const range_hours = 18 // hours

    // Calculate reference 'now' time
    const _now = date ? +date : Date.now(), now = _now - _now % 900000

    // Calculate the bounds for iteration
    const step_ms = 900000 // 15 minutes in milliseconds
    const max_steps = range_hours * 4 // Multiply the interval by 4 as per the instructions

    // Initialize a Map to store the data
    const time_map = new Map()

    // Iterate from lowerBound to upperBound in steps of 15 minutes
    for (let i = -max_steps; i <= max_steps; i++) {
        const date = new Date(now + i * step_ms)

        // Construct the DDHHMM integer
        const DD = String(date.getUTCDate()).padStart(2, '0')
        const HH = String(date.getUTCHours()).padStart(2, '0')
        const MM = String(date.getUTCMinutes()).padStart(2, '0')

        // Store the key and initialize the value as [i, []]
        time_map.set(parseInt('1' + DD + HH + MM), [i, []])
    }

    // Iterate over all timezones
    for (const tz_name of Intl.supportedValuesOf('timeZone')) {
        const formatter = new Intl.DateTimeFormat('en', {
            minute: '2-digit',
            hour: '2-digit',
            hourCycle: 'h23', // Use 24-hour format
            day: '2-digit',
            timeZone: tz_name,
        })

        // Format the date to get the DDHHMM key
        const formatted_date = formatter.formatToParts(now)
        const DD = formatted_date.find(part => part.type === 'day').value
        const HH = formatted_date.find(part => part.type === 'hour').value
        const MM = formatted_date.find(part => part.type === 'minute').value
        const key = parseInt('1' + DD + HH + MM)

        // Add the timezone to the map
        if (time_map.has(key))
            time_map.get(key)[1].push(tz_name)
        else
            console.error(`Error: Key ${key} not found in the time_map.`)
    }

    // Construct the result object
    const result = {}
    for (const [, [i, timezones]] of time_map)
        for (const timezone of timezones)
            // Manipulates 'i' to format the result accordingly to your needs
            result[timezone] = i

    return result
}

如果需要,可提供

UTC ±HH:MM
格式化程序:

function formatter(x) {
    return 'UTC '
        + String.fromCharCode(43 + ((x < 0) << 1))
        + String(~~((x = Math.abs(x)) * .25)).padStart(2, '0')
        + ':' + String((x % 4) * 15).padStart(2, '0')
}

对于您的具体输入,您可以使用:

const s = 'GMT -0800'

const h = +s.substring(s.length - 5, s.length - 2)
const m = +s.substring(s.length - 2)
const i = h * 4 + m / 15

const all_timezones = get_all_timezones_offsets(), res = [ ]
for(const tz_name in all_timezones)
    if (all_timezones[tz_name] === i)
        res.push(tz_name)

console.log(res)

今天的输出示例:

[
  'America/Anchorage',
  'America/Juneau',
  'America/Metlakatla',
  'America/Nome',
  'America/Sitka',
  'America/Yakutat',
  'Pacific/Pitcairn'
]
© www.soinside.com 2019 - 2024. All rights reserved.