Java中的时区转换

转载自 halfclear 原文:https://blog.csdn.net/halfclear/article/details/77573956

1.Date中保存的是什么
在java中,只要我们执行
Date date = new Date();
就可以得到当前时间。如:

Date date = new Date();
System.out.println(date);
  • 1
  • 2

输出结果是:
Thu Aug 24 10:15:29 CST 2017
也就是我执行上述代码的时刻:2017年8月24日10点15分29秒。是不是Date对象里存了年月日时分秒呢?不是的,Date对象里存的只是一个long型的变量,其值为自1970年1月1日0点至Date对象所记录时刻经过的毫秒数,调用Date对象getTime()方法就可以返回这个毫秒数,如下代码:

Date date = new Date();
System.out.println(date + ", " + date.getTime());
  • 1
  • 2

输出如下:
Thu Aug 24 10:48:05 CST 2017, 1503542885955
即上述程序执行的时刻是2017年8月24日10点48分05秒,该时刻距离1970年1月1日0点经过了1503542885955毫秒。反过来说,输出的年月日时分秒其实是根据这个毫秒数来反算出来的。

2.时区
全球分为24个时区,相邻时区时间相差1个小时。比如北京处于东八时区,东京处于东九时区,北京时间比东京时间晚1个小时,而英国伦敦时间比北京晚7个小时(英国采用夏令时时,8月英国处于夏令时)。比如此刻北京时间是2017年8月24日11:17:10,则东京时间是2017年8月24日12:17:10,伦敦时间是2017年8月24日4:17:10。

既然Date里存放的是当前时刻距1970年1月1日0点时刻的毫秒数,如果此刻在伦敦、北京、东京有三个程序员同时执行如下语句:

Date date = new Date();

那这三个date对象里存的毫秒数是相同的吗?还是北京的比东京的小3600000(北京时间比东京时间晚1小时,1小时为3600秒即3600000毫秒)?答案是,这3个Date里的毫秒数是完全一样的。确切的说,Date对象里存的是自格林威治时间( GMT)1970年1月1日0点至Date对象所表示时刻所经过的毫秒数。所以,如果某一时刻遍布于世界各地的程序员同时执行new Date语句,这些Date对象所存的毫秒数是完全一样的。也就是说,Date里存放的毫秒数是与时区无关的。

继续上述例子,如果上述3个程序员调用那一刻的时间是北京时间2017年8月24日11:17:10,他们继续调用

System.out.println(date);

那么北京的程序员将会打印出2017年8月24日11:17:10,而东京的程序员会打印出2017年8月24日12:17:10,伦敦的程序员会打印出2017年8月24日4:17:10。既然Date对象只存了一个毫秒数,为什么这3个毫秒数完全相同的Date对象,可以打印出不同的时间呢?这是因为Sysytem.out.println函数在打印时间时,会取操作系统当前所设置的时区,然后根据这个时区将同毫秒数解释成该时区的时间。当然我们也可以手动设置时区,以将同一个Date对象按不同的时区输出。可以做如下实验验证:

Date date = new Date(1503544630000L);  // 对应的北京时间是2017-08-24 11:17:10SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     // 北京
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));  // 设置北京时区SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区SimpleDateFormat londonSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 伦敦
londonSdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));  // 设置伦敦时区System.out.println("毫秒数:" + date.getTime() + ", 北京时间:" + bjSdf.format(date));
System.out.println("毫秒数:" + date.getTime() + ", 东京时间:" + tokyoSdf.format(date));
System.out.println("毫秒数:" + date.getTime() + ", 伦敦时间:" + londonSdf.format(date));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

输出为:
毫秒数:1503544630000, 北京时间:2017-08-24 11:17:10
毫秒数:1503544630000, 东京时间:2017-08-24 12:17:10
毫秒数:1503544630000, 伦敦时间:2017-08-24 04:17:10

可以看出,同一个Date对象,按不同的时区来格式化,将得到不同时区的时间。由此可见,Date对象里保存的毫秒数和具体输出的时间(即年月日时分秒)是模型和视图的关系,而时区(即Timezone)则决定了将同一个模型展示成什么样的视图。

3.从字符串中读取时间
有时我们会遇到从一个字符串中读取时间的要求,即从字符串中解析时间并得到一个Date对象,比如将"2017-8-24 11:17:10"解析为一个Date对象。现在问题来了,这个时间到底指的是北京时间的2017年8月24日11:17:10,还是东京时间的2017年8月24日11:17:10?如果指的是北京时间,那么这个时间对应的东京时间2017年8月24日12:17:10;如果指的是东京时间,那么这个时间对应的北京时间就是2017年8月24日10:17:10。因此,只说年月日时分秒而不说是哪个时区的,是有歧义的,没有歧义的做法是,给出一个时间字符串,同时指明这是哪个时区的时间。
从字符串中解析时间的正确作法是:指定时区来解析。示例如下:

String timeStr = "2017-8-24 11:17:10"; // 字面时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 设置北京时区
Date d = sdf.parse(timeStr);
System.out.println(sdf.format(d) + ", " + d.getTime());
  • 1
  • 2
  • 3
  • 4
  • 5

输出为:
2017-08-24 11:17:10, 1503544630000,

将一个时间字符串按不同时区来解释,得到的Date对象的值是不同的。验证如下:

String timeStr = "2017-8-24 11:17:10"; // 字面时间
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
Date bjDate = bjSdf.parse(timeStr);  // 解析
System.out.println("字面时间: " + timeStr +",按北京时间来解释:" + bjSdf.format(bjDate) + ", " + bjDate.getTime());SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区
Date tokyoDate = tokyoSdf.parse(timeStr); // 解析
System.out.println("字面时间: " + timeStr +",按东京时间来解释:"  + tokyoSdf.format(tokyoDate) + ", " + tokyoDate.getTime());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出为:
字面时间: 2017-8-24 11:17:10,按北京时间来解释:2017-08-24 11:17:10, 1503544630000
字面时间: 2017-8-24 11:17:10,按东京时间来解释:2017-08-24 11:17:10, 1503541030000
可以看出,对于"2017-8-24 11:17:10"这个字符串,按北京时间来解释得到Date对象的毫秒数是
1503544630000;而按东京时间来解释得到的毫秒数是1503541030000,前者正好比后者大于3600000毫秒即1个小时,正好是北京时间和东京时间的时差。这很好理解,北京时间2017-08-24 11:17:10对应的毫秒数是1503544630000,而东京时间2017-08-24 11:17:10对应的北京时间其实是2017-08-24 10:17:10(因为北京时间比东京时间晚1个小时),北京时间2017-08-24 10:17:10自然比北京时间2017-08-24 11:17:10少3600000毫秒。

4.将字符串表示的时间转换成另一个时区的时间字符串
综合以上分析,如果给定一个时间字符串,并告诉你这是某个时区的时间,要将它转换为另一个时区的时间并输出,正确的做法是:
1.将字符串按原时区转换成Date对象;
2.将Date对象格式化成目标时区的时间。
比如,将北京时间"2017-8-24 11:17:10"输出成东京时间,代码为:

String timeStr = "2017-8-24 11:17:10"; // 字面时间
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
Date date = bjSdf.parse(timeStr);  // 将字符串时间按北京时间解析成Date对象SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  // 东京
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));  // 设置东京时区
System.out.println("北京时间: " + timeStr +"对应的东京时间为:"  + tokyoSdf.format(date));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出为:
北京时间:2017-8-24 11:17:10对应的东京时间为:2017-08-24 12:17:10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从语言学到深度学习NLP,一文概述自然语言处理

来源:萤火虫沙龙2概要:自然语言处理(NLP)近来因为人类语言的计算表征和分析而获得越来越多的关注。自然语言处理(NLP)近来因为人类语言的计算表征和分析而获得越来越多的关注。它已经应用于许多如机器翻译、…

中国石油大学华东c语言答案全集,【2019年整理】中国石油大学华东C语言习题答案.pdf...

C 语言复习题【设计型】5.1 输出一行星号编写程序在一行中输出 N 个星号。输入&#xff1a; N 值输出&#xff1a; 一行中 N个星号#includeint main(){int a,i;scanf("%d",&a);for(i1;i<a;i)printf("*");printf("\n");return 0;}【设计型…

特老的文章:三层应该怎么划分。不知大家还有用否

可以用这样的思想&#xff1a; 最初的应用是单机&#xff0c;数据和功能都放在一台机器上。随着应用向工作组模式发展中&#xff0c;人们迫切需要 调用彼此的数据&#xff0c;也调用彼此的功能&#xff0c;这样人们就不用重复录入数据&#xff0c;程序员也不须重复写 功能。数据…

Guava RateLimiter限流原理解析

来源&#xff1a;https://zhuanlan.zhihu.com/p/60979444 限流是保护高并发系统的三把利器之一&#xff0c;另外两个是缓存和降级。限流在很多场景中用来限制并发和请求量&#xff0c;比如说秒杀抢购&#xff0c;保护自身系统和下游系统不被巨型流量冲垮等。 限流的目的是通过…

脑洞大开:未来二十年将兴起的88个微型产业

来源&#xff1a;资本实验室概要&#xff1a;目前&#xff0c;我们正在进入一个指数级技术变革的时代。这个时代既催生出前所未有的科技巨头&#xff0c;其实也催生了一个微型创新的新时代。目前&#xff0c;我们正在进入一个指数级技术变革的时代。这个时代既催生出前所未有的…

并查集算法c语言版,并查集及其C程序实现.doc

并查集及其C程序实现等价关系与等价类从数学上看&#xff0c;等价类是一个对象(或成员)的集合&#xff0c;在此集合中的所有对象应满足等价关系。若用符号"≡"表示集合上的等价关系&#xff0c;那么对于该集合中的任意对象x,y, z&#xff0c;下列性质成立&#xff1a…

Web 服务策略断言语言 (WS-PolicyAssertions)

原文&#xff1a;http://www.microsoft.com/china/msdn/library/webservices/webservices/WebServicesPolicyAssertionsLanguage(WS-PolicyAssertions).mspxWeb 服务策略断言语言 (WS-PolicyAssertions) 发布日期&#xff1a; 4/26/2004| 更新日期&#xff1a; 4/26/2004版本 1…

周志华:严肃的研究者就不该去触碰强人工智能

来源&#xff1a;知识分子概要&#xff1a;关于人工智能&#xff0c;长期存在两种不同的目标或者理念。关于人工智能&#xff0c;长期存在两种不同的目标或者理念。一种是希望借鉴人类的智能行为&#xff0c;研制出更好的工具以减轻人类智力劳动&#xff0c;一般称为“弱人工智…

几种限流器(RateLimiter)原理与实现

来源&#xff1a;https://blog.csdn.net/netyeaxi/article/details/104270337 限流器(RateLimiter)主要有两种算法&#xff1a; 漏桶算法 令牌桶算法 它们都是网络世界中流量整形&#xff08;Traffic Shaping&#xff09;或速率限制&#xff08;Rate Limiting&#xff09;时经…

c语言如何随机选择入口,c语言随机排列-----适用于初学者

本程序只是实现了基本的数字随机排列&#xff0c;如有不懂&#xff0c;留言提问。。。// 随机排序.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "time.h"#include "stdio.h"#include "stdlib.h"int _tmain(int …

The Best and the Worst

Joe Sanders has the most beautiful garden in our town. Nearly everybody enters for “The Nicest Garden Competition” each year,but Joe wins every time.Bill Friths garden is larger than Joes.Bill works harder than Joe and grows more flowlers and vegetables,…

guava限流器RateLimiter原理及源码分析

来源&#xff1a;https://www.cnblogs.com/zhandouBlog/p/11743660.html 前言 RateLimiter是基于令牌桶算法实现的一个多线程限流器&#xff0c;它可以将请求均匀的进行处理&#xff0c;当然他并不是一个分布式限流器&#xff0c;只是对单机进行限流。它可以应用在定时拉取接…

185页深度报告 扒一扒AI金融的老底【附下载】

来源&#xff1a;智东西概要&#xff1a;2016年&#xff0c;中国爆出8家独角兽&#xff0c;总估值964亿美元位冠全球&#xff1b;2017年&#xff0c;毕马威全球百佳金融科技企业前三甲&#xff0c;蚂蚁金服、众安保险、趣店&#xff0c;皆来自中国&#xff1b;过往两年&#xf…

夹娃娃动画Android,手机模拟抓娃娃

手机模拟抓娃娃让你通过手机足不出户也能感受娃娃机的乐趣,萌趣的卡通形象,清新治愈的设计风格,简单上手的玩法,赶快加入进来冲击最高分吧,点击下载手机模拟抓娃娃开始你的挑战&#xff01;手机模拟抓娃娃介绍手机模拟抓娃娃游戏是一款模拟进行的真人在线抓娃娃的掌上控制的休闲…

Inline Method(内联函数)

一个函数的本体与名称同样清楚易懂 int getRating() {return moreThanFiveLateDeliveries() ? 2 : 1; }boolean moreThanFiveLateDeliveries() {return numberOfLateDelivers > 5; } 重构后 int getRating() {return (numberOfLateDelivers > 5) ? 2 : 1; }

XML 简单操作

<?xml:namespace prefix o /> <?xml version"1.0" encoding"gb2312"?><bookstore> <book genre"fantasy" ISBN"2-3631-4"> <title>Oberons Legacy</title> <author>Corets, Ev…

android友盟错误日志,Taro(React-native)集成友盟错误日志分析U-App移动统计

1、先去友盟官网注册应用&#xff0c;获取到appkey&#xff0c;友盟移动统计分析U-App&#xff0c;这个步骤就不贴出来了&#xff0c;需要注意的是ios和Android 不能使用同一个appkey&#xff0c;需要分别创建两个应用&#xff0c;应用名称可以在后面加上平台名称&#xff0c;例…

2018年中国新零售市场研究报告——概念、模式与案例【附下载】

来源&#xff1a;亿欧概要&#xff1a;“新零售” 之“新”在于顺势下的“变化”&#xff0c;不应该局限于“阿里巴巴的新零售”。报告尝试从一个更宽广的视角&#xff0c;对当前零售业变化的背景和各种驱动因素进行分析&#xff0c;总结当下时间段零售行业参与者的新动作&…

[导入]ASP.NET 配置节架构

ASP.NET 配置节架构文章来源:http://blog.csdn.net/21aspnet/archive/2004/11/04/167417.aspx转载于:https://www.cnblogs.com/zhaoxiaoyang2/archive/2004/11/05/816261.html

重构--思维导图

#原图 System.out.println("https://www.processon.com/view/60fa8c441e085366ea4c2b9e?fromnew1");