JavaScript检查时区名称是否有效

34

是否有一种在JavaScript中检查时区名称是否有效的方法,而无需使用外部库?

当用户在文本字段中输入时区名称时,我想要验证该区域是否有效。

我知道我们可以使用moment-timezone库轻松完成此操作。但我不想使用任何额外的库。我正在寻找纯JavaScript的方法。

isValidTimeZone(name) {
//return true/false  
}

isValidTimeZone('Asia/Colombo'); //returns true
isValidTimeZone('America/Los_Angeles'); //returns true
isValidTimeZone('MyTimeZone/ME'); //returns false

1
时区的有效性并不基于友好的位置名称(正如您在问题中展示的那样),而是基于时区偏移量。https://dev59.com/yGEh5IYBdhLWcg3wRBn5 - Scott Marcus
用户输入时区名称(例如:亚洲/科伦坡)。稍后我需要在Highcharts中使用它。因此需要验证此内容。用户不会输入+05:30。 - Pratap A.K
什么使得一个时区对你来说是有效的?America/Anaheim 是有效的吗?因为我认为你并不是指任何以“Continent/City_Name”格式的内容都自动有效。你必须有一些数据库进行测试。 - Álvaro González
你觉得自己维护这个数据有必要吗?为了避免使用库而去做这么多麻烦的事情。 - Joe Clay
如果您不想使用外部库,那么就没有什么神奇的方法,只能自己编写一个映射表。可以访问 https://github.com/dmfilipenko/timezones.json 或 moment-timezone 作为参考。 - rstar
4
它们不仅仅是“友好”的名称,它们是时区数据库中的标识符。这里有一个列表:https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - Matt Johnson-Pint
3个回答

67
在完全支持 ECMA-402(ECMAScript 国际化 API)中的 IANA 时区标识符的环境中,您可以尝试在 DateTimeFormat 中使用时区(或在 toLocaleString 的选项中使用),如果它不是有效的时区,则会抛出异常。 您可以在支持它的环境中使用它来测试有效性,但只能在支持它的环境中使用。
function isValidTimeZone(tz) {
    if (!Intl || !Intl.DateTimeFormat().resolvedOptions().timeZone) {
        throw new Error('Time zones are not available in this environment');
    }

    try {
        Intl.DateTimeFormat(undefined, {timeZone: tz});
        return true;
    }
    catch (ex) {
        return false;
    }
}

// Usage:
isValidTimeZone('America/Los_Angeles') // true
isValidTimeZone('Foo/Bar') // false

如果您无法确保环境的一致性,那么最好的方法是使用moment-timezone。

!!moment.tz.zone('America/Los_Angeles') // true
!!moment.tz.zone('Foo/Bar') // false

当然,您可以始终提取自己的时区名称数组(也许使用moment.tz.names()),并针对该数组进行测试。


15

在TypeScript中,您还可以以更清晰的方式进行操作。

    public static isValidTimezone(timezone: string): boolean {
            return moment.tz.zone(timezone) != null;
        }

你还需要导入

import moment = require("moment-timezone");

8

我采用了Matt Johnson-Pin的解决方案,在编写单元测试后,我发现如果传递 undefined,该函数将返回true。因此,我进行了小的更新:

export const isValidTimeZone = (tz: unknown): boolean => {
    try {
        if (!Intl || !Intl.DateTimeFormat().resolvedOptions().timeZone) {
            return false
        }

        if (typeof tz !== 'string') {
            return false
        }

        // throws an error if timezone is not valid
        Intl.DateTimeFormat(undefined, { timeZone: tz })
        return true
    } catch (error) {
        return false
    }
}

谢谢,无论如何我都会在生产中使用这个。


只是补充一下,"在这个环境中无法使用时区"这句话并不完全正确。一些用户支持时区的设置可能由于某种原因(可能是浏览器偏好或其他原因)将时区的区域设置为未定义,但仍然能够在DateTimeFormat中使用时区,所以需要进行稍微不同的检查。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接