Date中保存的是什么
在java中,只要我们执行
Date date = new Date();
就可以得到当前时间。如:
Date date = new Date();
System.out.println(date);
输出结果是: 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());
输出结果是: Thu Aug 24 10:48:05 CST 2017, 1503542885955
即上述程序执行的时刻是2017年8月24日10点48分05秒,该时刻距离1970年1月1日0点经过了1503542885955毫秒。反过来说,输出的年月日时分秒其实是根据这个毫秒数来反算出来的。
时区的概念
全球分为24个时区,相邻时区时间相差1个小时。比如北京处于东八时区,东京处于东九时区,北京时间比东京时间晚1个小时,而英国伦敦时间比北京晚7个小时(英国采用夏令时时,8月英国处于夏令时)。比如此刻北京时间是2017年8月24日11:17:10,则东京时间是2017年8月24日12:17:10,伦敦时间是2017年8月24日4:17:10。调用Date对象getTime()方法就可以返回这个毫秒数。
Date的时区无关性
既然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里存放的毫秒数是与时区无关的。
Date 与 Sting 格式互转:
package utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Date 和 String
* 关于时间的格式,在应用中一般用 Stirng 和 Date 来表示,
*
* Date--> String 没有时区的概念,Date中的内容都是 国际的,当getHour() toString() 等方法时,
* 通过 获取本地的时区对Date进行格式转换再输出
*
* String --> Date 时,传递的 String,默认是本地的时区时间,如果传递的参数不是本地时区时间时,
* 在转换为 Date时,需要指定时区
*/
public class Test_TimeZone {
public static void main(String[] args) throws ParseException {
Date date = new Date();
System.out.println(date.getTime()); // 全球统一值
System.out.println(date.toString()); // toString的时候获取本地时区,做了时间转换,并不是Date的真实时间
System.out.println();
String date_str_1 = format(date);
System.out.println(date_str_1);
Date date_1 = parse(date_str_1);
System.out.println(date_1.toString());
/* 查看 支持的 TimeZone
String[] ss = TimeZone.getAvailableIDs();
for (String string : ss) {
if (string.indexOf("GMT") > 0) {
System.out.println(string);
}
}
*/
}
/**
* 日期格式转字符串 (Date -- > String)
* Date 转字符串,格式随便定义都可以
*/
public static String format(Date date) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
//df.setTimeZone(TimeZone.getTimeZone("Etc/GMT-8"));
df.setTimeZone(TimeZone.getTimeZone("GMT")); // 国际时间,决定输出的 String 是国际格式
return df.format(date);
}
/**
* 字符串转日期格式 (String --> Date)
*/
public static Date parse(String s) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
//df.setTimeZone(TimeZone.getTimeZone("Etc/GMT-8"));
df.setTimeZone(TimeZone.getTimeZone("GMT")); // 指定参数 String为国际格式,输出时,按本地时区输出
return df.parse(s);
}
}
将 某个时区 的 String 格式 转换为 另一个时区的 String 格式
package utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Test_Time {
public static void main(String[] args) throws ParseException {
parse_format();
}
/**
* 将 某个时区的 String 的格式 转换为 另一个时区的 String 格式
* @throws ParseException
*/
public static void parse_format() throws ParseException {
String timeStr = "2017-8-24 11:17:10";
/*
* 一般是通过 Date 转换过来的,Date 转换到 String 的时候 需要指定时区,所以得到的String是有时区的
* (当你此刻输入一个 String 格式的时间时,这个String一定是有时区的,所以 要深刻理解 String 是有时区的,
* 任何时候需要操作该值的时候,都要指定 String 代表的时区)
*/
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
bjSdf.setTimeZone(TimeZone.getTimeZone("GMT"));
/*
* 指定 字符串的时区
* 将字符串时间按 国际时间 解析成Date对象
* (因为你通过其他地方获取的 String 是国际时间格式,所以按照国际时间转换)
*/
Date date = bjSdf.parse(timeStr);
System.out.println(date.getTime());
/*
* 如果你获取的 是 本地的字符串时间,那就需要按照 本地的 时区转换,
* 转换成功之后,获取的Date都是国际格式,但是在 toString的时候,会默认按本地时区输出,但是输出内容并不是国际时间,
*
* 但getTime()是统一的,所以我们认为 Date 没有时区的概念,任何的输出操作都会先获取本地时区,将国际时间格式的Date,按本地时区输出。(输出内容不可信)
*/
SimpleDateFormat tokyoSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 东京
tokyoSdf.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo")); // 设置东京时区
System.out.println("国际时间: " + timeStr + " 对应的东京时间为:" + tokyoSdf.format(date));
/*
* 输出:
* 1503573430000
* 国际时间: 2017-8-24 11:17:10 对应的东京时间为:2017-08-24 20:17:10
* */
}
}
我觉得这两个例子,应该就能说明大部分问题了,
深刻理解 Date 没有时区的概念,任何的输出信息都是根据本地时区来输出的。
任何一个 String 格式的字符串都有相对应的时区,因为任何的String都是通过 new Date() 和 format() 转换过来的,即使没有写时区,当时默认也获取了本地时区。所以,Sting 一定有对应的时区。
参考博客:
https://blog.csdn.net/halfclear/article/details/77573956
https://www.cnblogs.com/softidea/p/8612287.html