Java编程系列Java判断世界各时区的夏令时冬令时
Posted 善良勤劳勇敢而又聪明的老杨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java编程系列Java判断世界各时区的夏令时冬令时相关的知识,希望对你有一定的参考价值。
热门系列:
目录
1.前言
2.正文
2.1 设置时区
2.2 判断夏令时、冬令时
3.结尾
1.前言
前段时间在做一个需求的时候,其中有一个环节是需要判断当前时段,是否属于夏令时或是冬令时!对于做过国际业务或是外贸业务的童靴,应该都可能有接触到这一块。
在我们国内,是以北京时间为准,但在美国、或是欧洲等其他地区,不仅都有各自的时区,并且一年中,还分为夏令时和冬令时两个阶段!所以,在解决这个问题时,我们需要注意到两个问题点:
1、怎么获取到对应的时区?
2、怎么判断是否属于夏令时或是冬令时?
2.正文
弄清楚问题点后,咱们直接开整!
2.1 设置时区
在这里,会有一个选择题出现!一般我们平时使用日期类的时候,都是基于
java.util.Date
这个工具类来使用的;其次,现在Java8也新出了一个时间类库:
java.time.LocalDate;
java.time.LocalDateTime;
java.time.LocalTime;
java.time.ZoneId;
java.time.ZonedDateTime;
java.time.zone.ZoneRules;
那这个时候,就得二选一啦。功能实现上,其实二者都是可选的,但是应该选哪一种,优劣对比之下呢。我本人,选择了后者!
为什么?Date时间类其实使用的时候,可读性比较差;这个时候,我们通常会使用SimpleDateFormat去进行格式化;此时,我们需要注意他的线程安全问题,例如使用format方法,但其实现源码如下:
private StringBuffer format(Date date, StringBuffer toAppendTo,
FieldDelegate delegate)
// Convert input date to time field list
calendar.setTime(date);
boolean useDateFormatSymbols = useDateFormatSymbols();
for (int i = 0; i < compiledPattern.length; )
int tag = compiledPattern[i] >>> 8;
int count = compiledPattern[i++] & 0xff;
if (count == 255)
count = compiledPattern[i++] << 16;
count |= compiledPattern[i++];
switch (tag)
case TAG_QUOTE_ASCII_CHAR:
toAppendTo.append((char)count);
break;
case TAG_QUOTE_CHARS:
toAppendTo.append(compiledPattern, i, count);
i += count;
break;
default:
subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
break;
return toAppendTo;
calendar是共享变量,并且这个共享变量没有做线程安全控制。当多个线程同时使用相同的SimpleDateFormat对象【如用static修饰的SimpleDateFormat】调用format方法时,多个线程会同时调用calendar.setTime方法,可能一个线程刚设置好time值另外的一个线程马上把设置的time值给修改了导致返回的格式化时间可能是错误的。
在多并发情况下使用SimpleDateFormat需格外注意SimpleDateFormat除了format是线程不安全以外,parse方法也是线程不安全的。parse方法实际调用alb.establish(calendar).getTime()方法来解析,alb.establish(calendar)方法里主要完成了:
- 重置日期对象cal的属性值
- 使用calb中中属性设置cal
- 返回设置好的cal对象
但是这三步不是原子操作!!!而后者,java8新推出的时间类LocalDate、LocalTime、LocalDateTime等都是不可变类且线程安全的!所以可以放心使用!至于具体使用方式,此处不做赘述,各位可自行了解!
时区有很多,但是通过java.time类库中java.time.ZoneId的源码,可以发现可供选择的有如下这些:
public abstract class ZoneId implements Serializable
/**
* A map of zone overrides to enable the short time-zone names to be used.
* <p>
* Use of short zone IDs has been deprecated in @code java.util.TimeZone.
* This map allows the IDs to continue to be used via the
* @link #of(String, Map) factory method.
* <p>
* This map contains a mapping of the IDs that is in line with TZDB 2005r and
* later, where 'EST', 'MST' and 'HST' map to IDs which do not include daylight
* savings.
* <p>
* This maps as follows:
* <ul>
* <li>EST - -05:00</li>
* <li>HST - -10:00</li>
* <li>MST - -07:00</li>
* <li>ACT - Australia/Darwin</li>
* <li>AET - Australia/Sydney</li>
* <li>AGT - America/Argentina/Buenos_Aires</li>
* <li>ART - Africa/Cairo</li>
* <li>AST - America/Anchorage</li>
* <li>BET - America/Sao_Paulo</li>
* <li>BST - Asia/Dhaka</li>
* <li>CAT - Africa/Harare</li>
* <li>CNT - America/St_Johns</li>
* <li>CST - America/Chicago</li>
* <li>CTT - Asia/Shanghai</li>
* <li>EAT - Africa/Addis_Ababa</li>
* <li>ECT - Europe/Paris</li>
* <li>IET - America/Indiana/Indianapolis</li>
* <li>IST - Asia/Kolkata</li>
* <li>JST - Asia/Tokyo</li>
* <li>MIT - Pacific/Apia</li>
* <li>NET - Asia/Yerevan</li>
* <li>NST - Pacific/Auckland</li>
* <li>PLT - Asia/Karachi</li>
* <li>PNT - America/Phoenix</li>
* <li>PRT - America/Puerto_Rico</li>
* <li>PST - America/Los_Angeles</li>
* <li>SST - Pacific/Guadalcanal</li>
* <li>VST - Asia/Ho_Chi_Minh</li>
* </ul>
* The map is unmodifiable.
*/
public static final Map<String, String> SHORT_IDS;
static
Map<String, String> map = new HashMap<>(64);
map.put("ACT", "Australia/Darwin");
map.put("AET", "Australia/Sydney");
map.put("AGT", "America/Argentina/Buenos_Aires");
map.put("ART", "Africa/Cairo");
map.put("AST", "America/Anchorage");
map.put("BET", "America/Sao_Paulo");
map.put("BST", "Asia/Dhaka");
map.put("CAT", "Africa/Harare");
map.put("CNT", "America/St_Johns");
map.put("CST", "America/Chicago");
map.put("CTT", "Asia/Shanghai");
map.put("EAT", "Africa/Addis_Ababa");
map.put("ECT", "Europe/Paris");
map.put("IET", "America/Indiana/Indianapolis");
map.put("IST", "Asia/Kolkata");
map.put("JST", "Asia/Tokyo");
map.put("MIT", "Pacific/Apia");
map.put("NET", "Asia/Yerevan");
map.put("NST", "Pacific/Auckland");
map.put("PLT", "Asia/Karachi");
map.put("PNT", "America/Phoenix");
map.put("PRT", "America/Puerto_Rico");
map.put("PST", "America/Los_Angeles");
map.put("SST", "Pacific/Guadalcanal");
map.put("VST", "Asia/Ho_Chi_Minh");
map.put("EST", "-05:00");
map.put("MST", "-07:00");
map.put("HST", "-10:00");
SHORT_IDS = Collections.unmodifiableMap(map);
上述时区简写,可以自行了解。我贴一下,我本次使用到的一些常见时区简称中文版:
<timezone id="Asia/Shanghai">中国标准时间 (北京)</timezone>
<timezone id="Asia/Hong_Kong">香港时间 (香港)</timezone>
<timezone id="Asia/Taipei">台北时间 (台北)</timezone>
<timezone id="Asia/Seoul">首尔</timezone>
<timezone id="Asia/Tokyo">日本时间 (东京)</timezone>
<timezone id="America/New_York">美国东部时间 (纽约)</timezone>
<timezone id="America/Denver">美国山区时间 (丹佛)</timezone>
<timezone id="America/Costa_Rica">美国中部时间 (哥斯达黎加)</timezone>
<timezone id="America/Chicago">美国中部时间 (芝加哥)</timezone>
<timezone id="America/Mexico_City">美国中部时间 (墨西哥城)</timezone>
<timezone id="America/Regina">美国中部时间 (里贾纳)</timezone>
<timezone id="America/Los_Angeles">美国太平洋时间 (洛杉矶)</timezone>
<timezone id="America/Tijuana">美国太平洋时间 (提华纳)</timezone>
<timezone id="America/Phoenix">美国山区时间 (凤凰城)</timezone>
现在,贴下时区设置的代码:
//例如设置美国纽约时区,并获取纽约当前时间
ZoneId zoneId = ZoneId.of("America/New_York");
LocalDateTime localDateTime = LocalDateTime.now(zoneId);
2.2 判断夏令时、冬令时
在判断都夏冬令时之前,我们得知道各个时区的冬夏令时计时规则!这里有一个时区大全的传送门,各位按需查看!我本次需要判断美国、欧洲两个地区的夏冬令时,所以其计时规则如下:
美国
夏令时:每年3月第一个星期六到11月第二个星期日;
冬令时:每年3月第二个星期日到11月第一个星期六;
欧洲
夏令时:每年3月的最后一个星期天的凌晨1点开始,十月最后一个星期天凌晨1点结束;
冬令时:每年十月的最后一个星期天的凌晨1点开始,到第二年的三月份的最后一个星期天的凌晨1点结束;
但是,其实我们通过以下代码,就可以直接判断,当前时区,是处在夏令时还是冬令时了:
//还是以美国纽约时区为例
ZoneId zoneId = ZoneId.of("America/New_York");
//获取当前时区当前时间
LocalDateTime localDateTime = LocalDateTime.now();
//设置ZonedDateTime对象
ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
//获取时区计时规则
ZoneRules rules = zoneId.getRules();
//true表示处于夏令时,否则冬令时
boolean result = rules.isDaylightSavings(zonedDateTime.toInstant());
3.结尾
以上内容,作为开发记录,也是一种分享,希望能帮助到有需要的朋友!若有错误,也欢迎大家积极留言指正、讨论!
二维码内,有我个人平时收集而来的2T资料,有网盘存储,长期有效!有兴趣的同学,可以扫码关注我的个人公众号:时代名猿,回复关键字:wyzl,领取一线资料!
以上是关于Java编程系列Java判断世界各时区的夏令时冬令时的主要内容,如果未能解决你的问题,请参考以下文章