时间和日期
java 8 LocalDateTime 20 例
http://www.importnew.com/15637.html
认识时间与日期
一、时间的度量
1.格林威治标准时间
Greenwich Mean Time,简称GMT时间,一开始是参考知自格林威治皇家天文台的标准太阳时间,格林威治标准时间的正午时太阳抵达太阳最高点之时。GMT通过观察太阳而得,然而地球公转轨道为椭圆形且速度不一,本身自转亦缓慢减速中,因而会造成越来越大的时间误差,现在GMT已经不作为标准时间使用。
2.世界时
Universal Time,简称UT,是借由观测远方星体跨过子午线而得,这会比观测太阳来的准确一些。公元1935年International Astronomical Union建议使用更精确的UT来取代GMT,在1972年引入UTC之前,GMT和UT是相同的。
3.国际原子时
UT仍然受地球自转速度的影响而有误差。1967年定义的国际原子时(internaitional atomic time,TAI),将秒的国际单位定义为铯原子辐射振动9192631770周耗费的时间,时间从UT的1958开始同步。
4.世界协调时间
由于铯原子振动定义的秒长是固定的,然而地球自转原来越慢会使得TAI的时间会不断超前基于地球自转的UT的UT时间,为了两者差距不要过大,提出了(Cooidinated Universal Time,UTC).
UTC经过几次的修正,为了简化日后对时间的修正,1972年UTC采用闰秒修正,确保UTC与UT的时间不会超过0.9秒,加入闰秒的时间一般会是六月或者十二月底。最近一次的闰秒修正为2012年6月30日,当时的TAI实际上已经超前UTC35秒之前。
5.Unix时间
Unix系统的时间表示法,定义为UTC时间在1970年1月1日00:00:00为起点而经过的秒数,不考虑闰秒修正,用于表达时间轴上的 某一瞬间。
6.epoch
1970年1月1日00:00:00为时间表示法的起算点
时间总结
△就目前来,即使标注是GMT(文件或是API),实际上谈到的时间指的是UTC时间。
△秒的单位是基于TAI,也就是铯原子的振动次数。
△地球自转越来越慢而有闰秒修正,确保UTC与UT的时间不会超过0.9秒最近一次的闰秒修正为2012年6月30日,当时的TAI实际上已经超前UTC35秒之前。
△UTC时间在1970年1月1日00:00:00为起点而经过的秒数,不考虑闰秒修正,不少来自Unix的系统、平台、软件等,也都选择这个时间表示法做为起算点。
二、年历的简介
1.儒略历
儒略历(Julian Calendar)是现今公历的前身,用来取代罗马日历,与公元前46年被Julian Caesar采纳,公元前45年实现,约于公元4年至1582年广为被各地采用。儒略历修正了罗马日历三年设置一闰年的错误,改采四年一闰。
2.格里高日历
格里高日历(Gregorian Calendar)改革了儒略历,由教宗Pope GregoryXIII与1582年颁行,将儒略历1582年的10月4日的隔天定为格里高日历1582年10月15日周五。各个国家改历时间不相同,英国,大英帝国(美国东部)1752年九月初。
3.ISO 8601标准
ISO8601并非年历系统而是时间日期的表示方法的标准,用以统一时间日期的数据交换格式,例如:yy-mm-ddTHH:MM:SS.SSS之类的标准格式。在数据格式上不部分与格里高日历相同,因而有些处理时间数据的程序或API,为了符合日期交换数据的标准,会采用ISO 8601。在ISO 8601中的19世纪是指1900到1999年而格里高日历中是指1801到1900。
三、认识时区
UTC偏移(Offset),大致来说,经度每15度是偏移一小时,美国采用四个时区而中国印度只采用一个时区。
认识Date与Calendar
一、时间轴上瞬间的Date
如果想要取得系统时间,方法之一就是使用System.currentTimeMillis()方法,返回的是long类型的整数,代表的是1970年一月一日0时0分0秒0毫秒至今经过的毫秒数。
Date date1=new Date(currentTimeMillis());
Date date2=new Date();
out.println(date1.getTime());
out.println(date2.getTime());
结果:1398741380778
1398741380778
/*
* 取得系统的时间
*/
public class DateDemo1 {
public static void main(String args[]) {
System.out.println(System.currentTimeMillis());
}
输出为:1311060393171
执行结果会显示从1970年1月1日开始到取得系统时间为止所经过的毫秒数,例如1115346430703这个数字,但这样的数字没有人确切了解它的意 义是什么,您可以使用Date类别来让这个数字变的更有意义一些
Date的toString()虽然可以按内含的epoch毫秒数来返回可以读懂的字符串dow(星期) mon(月)dd(日) hh:mm:ss zzz(时区) yyyy(公元年),Date时区无法改变,所以toString和toLocalString()toGMTString()被废弃了。
二、格式化时间日期的DateFormat
Java.text.DateFormat,.DateFormat是一个抽象类,其操作类是Java.text.SimpleDateFormat,可直接构建SimpleDateFormat实例,或是使用DateFormat的getDateInstance()getTimeINstance()getDateTimeInstance()等静态方法取得SimpleDateFormat实例
public class DateDemo4 {
public static void main(String[] args) {
Date date = new Date();
DateFormat shortFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
DateFormat mediumFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
DateFormat longFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
DateFormat fullFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
System.out.println(shortFormat.format(date));
System.out.println(mediumFormat.format(date));
System.out.println(longFormat.format(date));
System.out.println(fullFormat.format(date));
System.out.println(getDateInstance(LONG).formate(date))
}
}
输出结果为:
11-7-19 下午3:33
2011-7-19 15:33:54
2011年7月19日 下午03时33分54秒
2011年7月19日 星期二 下午03时33分54秒 CST
public class DateDemo5 {
public static void main(String args[]) {
Date date = new Date();
Locale locale = new Locale("en", "US");
DateFormat shortDateFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale);
DateFormat mediumDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
DateFormat longDateFormat = DateFormat.getDateInstance(DateFormat.LONG, locale);
DateFormat fullDateFormat = DateFormat.getDateInstance(DateFormat.FULL, locale);
System.out.println(shortDateFormat.format(date));
System.out.println(mediumDateFormat.format(date));
System.out.println(longDateFormat.format(date));
System.out.println(fullDateFormat.format(date));
}
}
输出结果为:
[java] view plain copy
7/19/11
Jul 19, 2011
July 19, 2011
Tuesday, July 19, 2011
补充
△Locale地区信息
地区信息可以由语言编码和可选的地区编码来指定,由两个小写字母,如ca表示加拿大,zh表示中文。地区编码由两个大写字母表示,定义在ISO-3166(http://blog.csdn.net/leixingjing/article/details/6709749)
建立代表台湾繁体中文的Locale
new Locale("zh","TW");
直接构建SimpleDateFormat的好处是,可以使用模式字符串自定义格式。EE-MM-dd-yyyy每个字符的定义可以参照SimpleDateFormat的API说明。
import java.text.*;
import java.util.*;
public class Learn {
public static void main(String[] args) {
DateFormat dateFormat=new SimpleDateFormat(args.length==0?"EE-MM-dd-yyyy":args[0]);
System.out.println(dateFormat.format(new Date()));
}
}
输出结果为:星期日-10-29-2017
SimpleDateFormat中的Parse()方法,可以按照构建SimpleDateFormat时指定的格式,将指定的字符串剖析为Date实例。例如:
import java.text.*;
import java.util.*;
public class Learn {
public static void main(String[] args) throws ParseException {
System.out.println("输入出生年月(yyyy-mm-dd)");
DateFormat dateFormat=new SimpleDateFormat("yyyy-mm-dd");
Date date=dateFormat.parse(new Scanner(System.in).nextLine());
System.out.println(dateFormat.format(date));
}
}
输入出生年月(yyyy-mm-dd)
1995-04-12
1995-04-12
三、处理时间日期的Calendar
java.util.Calendar
java.util.GregorianCalendar
Calendar是一个抽象类,操作了儒略历和格里高日历的混合日历,通过getInstance()取得Calendar实例默认就是取得.GregorianCalendar 实例。取得实例后通过getTime()取得Date实例,如果想要取得某年某月等时间字段,可以使用Get()方法并指定字段枚举常数。如
Calendar calendar=Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));//2017
System.out.println(calendar.get(Calendar.MONTH));//9
System.out.println(calendar.get(Calendar.DATE));//29
结果为:
2017
9
29
System.out.println(calendar.get(Calendar.YEAR));//2017
System.out.println(calendar.get(Calendar.MONTH));//9
System.out.println(calendar.get(Calendar.DATE));//29
calendar.add(Calendar.MONTH, 1);
calendar.add(Calendar.YEAR, 1);
calendar.add(Calendar.DATE, 1);
结果为:
2018
10
30
这个范例的时间是:2017/10/29
public static final int JANUARY 0
public static final int FEBRUARY 1
public static final int MARCH 2
public static final int APRIL 3
public static final int MAY 4
.......
如果2014/07/31则在date加一后为2014/08/01如果只想对日期中的某个字段加减则可以使用roll();
calendar.roll(Calendar.MONTH, 1);
默认的格里高日历年10.25星期五。日历时间可以用setGregorianChange()方法来修改,儒略历:Date(LONG.MAX_VALUE)格里高日历:Date(LONG.MIN_VALUE)
Calendar calendar=Calendar.getInstance();
calendar.set(1582,Calendar.OCTOBER,15);
System.out.println(calendar.getTime());//显示格里高日历1582 10.25
calendar.add(Calendar.DAY_OF_MONTH,-1);
System.out.println(calendar.getTime());//显示儒略历1582年10.4
四、设定TimeZone
使用Calendar时若没有使用时区信息会使用默认时区,你可以使用Java.util.TimeZone 的getDefault()来取得默认时区信息。
TimeZone timezone=TimeZone.getDefault();
System.out.println(timezone.getDisplayName());
System.out.println("\t时区ID:"+timezone.getID()+"\n\t日光节数:"+timezone.getDSTSavings()+"\n\t偏移毫秒数:"+timezone.getRawOffset());
/* 结果为:
中国标准时间
时区ID:Asia/Shanghai
日光节数:0
偏移毫秒数:28800000*/
TimeZone timezone1=TimeZone.getTimeZone("Asia/Taipei"); //取得指定时区的实例
Calendar calendar=Calendar.getInstance(timezone1);
System.out.println(calendar.getTimeZone().getDisplayName()+"\n"+calendar.get(Calendar.HOUR)+":"+calendar.get(Calendar.MINUTE));
/*
结果为:
中国标准时间
11:30
*/
五、JDK8新时间日期API
机器时间观点的API
Date看起来像是人类时间的概念实际上是机器时间的概念。
out.println(calendar.gettime())// Tue Apr 01 00:00:00 CDT 1975获得的是Date实例
out.println(calendar.gettime().gettime())//165513600484获得epoch毫秒数
对于机器时间概念,设计了Instant类,用以代表自定义的Javaepoch(1970年1月1日)之后的某个时间点历经的毫秒数,精确度基本上是毫秒,但可以添加纳秒精度的修正数值。
Instant的静态方法now()取得Instant实例ofEpochMilli()可以指定毫秒数,ofEpochSecond()可以指定秒数,可以使用plusSeconds()、plusMillis()、plusNanos()、minuSeconds()、minusMillis()、minusNanos()来做时间轴上的运算。。
Java 8中 java.util.Date 类新增了两个方法,分别是from(Instant instant)和toInstant()方法
// Obtains an instance of Date from an Instant object.
instant->date
public static Date from(Instant instant) {
try {
return new Date(instant.toEpochMilli());
} catch (ArithmeticException ex) {
throw new IllegalArgumentException(ex);
}
}
// Converts this Date object to an Instant.
date->instant
public Instant toInstant() {
return Instant.ofEpochMilli(getTime());
}