Java中的时区验证

16

我有一个字符串,我需要检查它是否为标准时区标识符。我不确定我需要使用哪种方法。

String timeZoneToCheck = "UTC";

我想确认它是否代表了一个有效的时区。

9个回答

36

你可以一行写成

public boolean validTimeZone(String timezone) {
    return Set.of(TimeZone.getAvailableIDs()).contains(timezone);
}

或者,您可以为其创建一个静态字段。

private static final Set<String> TIMEZONES = Set.of(TimeZone.getAvailableIDs())
public boolean validTimeZone(String timezone) {
    return TIMEZONES.contains(timezone);
}

1
最好使用 Set - Yan Khonski
仅适用于有效的Java 9及以上版本。不幸的是,我仍在使用8版本。 - Kevin M
这在 Kotlin 中会抛出类型推断错误。 private val TIMEZONES: HashSet<String> = setOf(TimeZone.getAvailableIDs()) 因为 getAvailableIDs 返回的是一个数组而不是 String。 - Tarnished-Coder

18
您可以使用getAvailableIDs()获取所有支持的ID。
然后循环支持的ID数组并与您的字符串进行比较。
示例:
String[] validIDs = TimeZone.getAvailableIDs();
for (String str : validIDs) {
      if (str != null && str.equals("yourString")) {
        System.out.println("Valid ID");
      }
}

13

java.time.ZoneId

只需要简单地使用ZoneId.of("Asia/Kolkata")即可。

try {
    ZoneId.of("Asia/Kolkataa");
} catch (Exception e) {
    e.printStackTrace();
}

如果您输入了无效的时区,它将会抛出异常。

**java.time.zone.ZoneRulesException: Unknown time-zone ID: Asia/Kolkataa**

6

这种解决方案比循环检查所有可能的ID更有效率。它检查getTimeZone的输出结果。

Java文档(TimeZone#getTimeZone):

返回: 指定的TimeZone,如果给定的ID无法理解,则返回GMT区域。

因此,如果输出是GMT时区,则输入是无效的,除非输入实际上是"GMT"。

public static boolean isValidTimeZone(@NonNull String timeZoneID) {
    return (timeZoneID.equals("GMT") || !TimeZone.getTimeZone(timeZoneID).getID().equals("GMT"));
}

如果您想在不调用 getTimeZone 两次的情况下使用有效的时区:

TimeZone timeZone = TimeZone.getTimeZone(timeZoneToCheck);
if(timeZoneToCheck.equals("GMT") || !timeZone.getID().equals("GMT")) {
    // TODO Valid - use timeZone
} else {
    // TODO Invalid - handle the invalid input
}

4
我建议采用以下解决方案:
public static final String GMT_ID = "GMT";
public static TimeZone getTimeZone(String ID) {
    if (null == ID) {
        return null;
    }

    TimeZone tz = TimeZone.getTimeZone(ID);

    // not nullable value - look at implementation of TimeZone.getTimeZone
    String tzID = tz.getID();

    // check if not fallback result 
    return GMT_ID.equals(tzID) && !tzID.equals(ID) ? null : tz;
}

如果时区ID无效或只是自定义时区无效,则会返回null。此外,您可以引入相应的null值处理程序(取决于用例) - 抛出异常等。


2
除了显而易见的事实,即您的方法将对有效的ID“GMT”(或任何等效ID)返回null。 - Piotr Findeisen
进一步解释一下:有很多(大约200个?)有效的tzid字符串是其他tzid的别名。例如,当您请求“US/Pacific”时,您会得到有效且等效的时区“America/Los_Angeles”。 - benkc

3
private boolean isValidTimeZone(final String timeZone) {
    final String DEFAULT_GMT_TIMEZONE = "GMT";
    if (timeZone.equals(DEFAULT_GMT_TIMEZONE)) {
        return true;
    } else {
        // if custom time zone is invalid,
        // time zone id returned is always "GMT" by default
        String id = TimeZone.getTimeZone(timeZone).getID();
        if (!id.equals(DEFAULT_GMT_TIMEZONE)) {
            return true;
        }
    }
    return false;
}

该方法对以下情况返回true:
assertTrue(this.isValidTimeZone("JST"));
assertTrue(this.isValidTimeZone("UTC"));
assertTrue(this.isValidTimeZone("GMT"));
// GMT+00:00
assertTrue(this.isValidTimeZone("GMT+0"));
// GMT-00:00
assertTrue(this.isValidTimeZone("GMT-0"));
// GMT+09:00
assertTrue(this.isValidTimeZone("GMT+9:00"));
// GMT+10:30
assertTrue(this.isValidTimeZone("GMT+10:30"));
// GMT-04:00
assertTrue(this.isValidTimeZone("GMT-0400"));
// GMT+08:00
assertTrue(this.isValidTimeZone("GMT+8"));
// GMT-13:00
assertTrue(this.isValidTimeZone("GMT-13"));
// GMT-13:59
assertTrue(this.isValidTimeZone("GMT+13:59"));
// NOTE: valid time zone IDs (see TimeZone.getAvailableIDs())
// GMT-08:00
assertTrue(this.isValidTimeZone("America/Los_Angeles"));
// GMT+09:00
assertTrue(this.isValidTimeZone("Japan"));
// GMT+01:00
assertTrue(this.isValidTimeZone("Europe/Berlin"));
// GMT+04:00
assertTrue(this.isValidTimeZone("Europe/Moscow"));
// GMT+08:00
assertTrue(this.isValidTimeZone("Asia/Singapore"));

...并且以下时区为false:

assertFalse(this.isValidTimeZone("JPY"));
assertFalse(this.isValidTimeZone("USD"));
assertFalse(this.isValidTimeZone("UTC+8"));
assertFalse(this.isValidTimeZone("UTC+09:00"));
assertFalse(this.isValidTimeZone("+09:00"));
assertFalse(this.isValidTimeZone("-08:00"));
assertFalse(this.isValidTimeZone("-1"));
assertFalse(this.isValidTimeZone("GMT+10:-30"));
// hours is 0-23 only
assertFalse(this.isValidTimeZone("GMT+24:00"));
// minutes 00-59 only
assertFalse(this.isValidTimeZone("GMT+13:60"));

1

如果TimeZone.getAvailableIDs()包含所询问的ID,则它是有效的:

public boolean validTimeZone(String id) {
    for (String tzId : TimeZone.getAvailableIDs()) {
            if (tzId.equals(id))
                return true;
    }
    return false;
}

很不幸,TimeZone.getTimeZone() 方法会默默地丢弃无效的时区 ID 并返回 GMT:

返回值:

指定的时区,如果给定的 ID 无法理解,则返回 GMT 时区。


我在想是否有一种验证ID的方法,而不是遍历所有的ID,因为这只会丢弃无效的ID并返回GMT。谢谢你们的回答。 - user1772643

1
你可以使用 TimeZone.getAvailableIDs() 获取受支持的 ID 列表。
for (String str : TimeZone.getAvailableIDs()) {
    if (str.equals("UTC")) {
        //found
    }
}

1

TimeZone#getTimeZone(String id)方法如果传入的值无效,则返回默认时区而不是返回一个无效的时区。因此,如果重新解释的值与初始值不匹配,则说明它是无效的。

private static boolean isValidTimeZone(@Nonnull String potentialTimeZone)
{
    // If the input matches the re-interpreted value, then the time zone is valid.
    return TimeZone.getTimeZone(potentialTimeZone).getID().equals(potentialTimeZone);
}

1
不行,因为有很多有效的tzid字符串是其他tzid的别名。例如,当您请求“US/Pacific”时,会返回有效且等效的时区“America/Los_Angeles”。 - benkc
你可能仍然需要GMT检查,如上面的答案所建议的 https://dev59.com/4Gcs5IYBdhLWcg3wJglV#17926927 - Venkateswara Rao

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