yyyy-MM-dd'T'HH:mm:ss.SSSXXX
。格林尼治时间已经再也不被做为标准时间使用,UTC 是最主要的世界时间标准。html
Java提供了获取当前时间的方法java
1970-01-01 00:00:00.000
的毫秒差值。返回的long值能够用来初始化java.util.Date, java.sql.Date, java.sql.Timestamp和java.util.GregorianCalendar对象。例如,要测量一些代码须要执行多长时间,实现以下,sql
long startTime = System.nanoTime(); //...the code being measured long estimatedTime = System.nanoTime() - startTime;
时间粒度
事实上System.currentTimeMillis()方法的时间粒度是大于1毫秒的。若是你反复执行这个方法,你会发现短期内获得的结果是相同的,随后又忽然在某一次结果增长了几十毫秒(也可能更多)。这是很正常的,毕竟这个方法确定不是世界上最精密的计时器。api
旧的时间API存在诸多问题,例如安全
java.util.Date类用于封装日期及时间信息,通常仅用它显示某个日期,不对他做任何操做处理,做处理推荐用Calendar类,计算方便。如下已过期的方法没有列出,可自行查看jdk文档多线程
构造方法oracle
Date() :分配 Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。app
Date(long date):分配 Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。学习
//一、使用Date类获取当前系统时间 Date date = new Date(); System.out.println(date); //因为Date类覆盖了toString()方法,因此能够直接输出Date类型的对象 //输出结果为Fri May 31 10:51:18 GMT+08:00 2019 /*给Date设置年份须要减去 1900 *输出结果Tue Jul 01 00:00:00 GMT+08:00 3919 *原来这里存在一个起始年份 1900,实际年份是要在你的年份参数上加上个起始年份。 */ Date date1 = new Date(2019,5,31); System.out.println(date1); //2.分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。 Date date2 = new Date(System.currentTimeMillis());//参数为19701月1日以来的毫秒数 Date date3 = new Date(1559284293556l); //long类型要加l System.out.println(date2); System.out.println(date3); //其余Date方法摘要可查看api
java.util.Calendar类用于封装日历信息,其主做用在于其方法能够对时间份量进行运算。Calendar类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操做日历字段(例如得到下星期的日期)提供了一些方法。线程
因为Calendar类是抽象类,且Calendar类的构造方法是protected的,因此没法使用Calendar类的构造方法来建立对象,API中提供了getInstance方法用来建立对象。
Java只提供java.util.GregorianCalendar这一种java.util.Calendar的实现类,能够直接新建出来使用:
Calendar calendar = new GregorianCalendar();//新建出来的calendar默认时间为当前时间,或者说建立出这个对象的时间。
经过Calendar的静态方法获取一个实例该方法会根据当前系统所在地区来自行决定时区,帮咱们建立Calendar实例,这里要注意,实际上根据不一样的地区,Calendar有若干个子类实现。而Calendar自己是抽象类,不能被实例化!咱们不须要关心建立的具体实例为哪一个子类,咱们只须要根据Calendar规定的方法来使用就能够了。
日历类所解决的根本问题是简化日期的计算,要想表示某个日期还应该使用Date类描述。Calendar是能够将其描述的时间转化为Date的,咱们只须要调用其getTime()方法就能够获取描述的日期的Date对象了。
经过日历类计算时间:为日历类设置时间,日历类设置时间使用通用方法set。set(int field,int value),field为时间份量,Calendar提供了相应的常量值,value为对应的值。
只有月份从0开始:0为1月,以此类推,11为12月,其余时间是正常的从1开始。也可使用Calendar的常量 calendar.NOVEMBER……等。
Calendar.DAY_OF_MONTH 月里边的天---号; Calendar.DAY_OF_WEEK 星期里的天---星期几 Calendar.DAY_OF_YEAR 年里的天 Calendar calendar=Calendar.getInstance();//构造出来表示当前时间的日历类 Date now=calendar.getTime();//获取日历所描述的日期 calendar.set(Calendar.YEAR, 2019);//设置日历表示2019年 calendar.set(Calendar.DAY_OF_MONTH,15);//设置日历表示15号 calendar.add(Calendar.DAY_OF_YEAR, 22);//想获得22天之后是哪天 calendar.add(Calendar.DAY_OF_YEAR, -5);//5天之前是哪天 calendar.add(Calendar.MONTH, 1);获得1个月后是哪天 System.out.println(calendar.getTime());
获取当前日历表示的日期中的某个时间单位可使用get方法。
int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(year+"年"+(month+1)+"月"+day+"日");//month要处理
经常使用构造方法
SimpleDateFormat(String pattern),pattern -为描述日期和时间格式的模式
用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。 注:此构造方法可能不支持全部语言环境。要覆盖全部语言环境,请使用 DateFormat 类中的工厂方法。
经常使用方法
public final String format(Date date)将一个 Date 格式化为日期/时间字符串 public Date parse(String source)throws ParseException从给定字符串的开始解析文本,以生成一个日期。
字符串转成Date对象
//建立一个SimpleDateFormat而且告知它要读取的字符串格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateFormat = "2019-05-31";//建立一个日期格式字符串 //将一个字符串转换为相应的Date对象 Date date = sdf.parse(dateFormat);//要先捕获异常 System.out.println(date);//输出这个Date对象
Date对象转成字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = new Date(); String dateStr = sdf.format(date);//把日期对象传进去,继承自DateFormat类的方法。将一个Date格式化为日期/时间字符串
在日期格式中,-和空格无特殊意义。无特殊含义的都原样输出
//将当前系统时间转换为2012/05/14 17:05:22的效果 SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); dateStr=format1.format(date); System.out.println(dateStr);
java.text.DateFormat类(抽象类)是SimpleDateFormat类的父类,用的少,没SimpleDateFormat灵活。
java.sql.Date继承java.util.Date,为了把前者转为后者,须要如下代码
Date date = new Date(); //java.sql.Date 不支持Date参数的构造器,传入long类型的时间 java.sql.Date d = new java.sql.Date(date.getTime()); System.out.println(d); System.out.println(d.getHours());
输出结果
2019-05-31 Exception in thread "main" java.lang.IllegalArgumentException at java.sql.Date.getHours(Unknown Source) at DateTest.DateTest1.main(DateTest1.java:40)
这是因为java.sql.Date是SQL中的单纯的日期类型,没有时分秒。故通常经过JDBC插入java.sql.Date数据时,会发现时分秒都没有。所以,若是同时须要日期和时间,应该使用Timestamp。它也是 java.util.Date 的子类,Timestamp 则包含时间戳的完整信息。
java.sql.Timestamp是java.util.Date的派生类(继承),因此在java.util.Date上能作的事,也能够在java.sql.Timestamp上作。
若是当前是2019-06-01 14:35,你建立一个java.sql.Date 将只记下2019-06-01这个信息。若你须要保留时间进行JDBC操做,请使用java.sql.Timestamp代替。
long time = System.currentTimeMillis(); java.sql.Timestamp timestamp = new java.sql.Timestamp(time); timestamp.setNanos(123456); int nanos = timestamp.getNanos(); // nanos = 123456
如今的Date类中大部分方法已经弃用,如今通常使用旧的API,Date只负责存储一个时间,并对Calendar和DateFormat提供操做接口。Calendar获取Date中特定的信息,对日期时间进行操做,SimpleDateFormat对日期时间进行格式化输入输出。
总的来讲,Date、Calendar 和 DateFormat 已经可以处理通常的时间日期问题了。可是不可避免的是,它们依然很繁琐,很差用而且这些日期类都是可变且线程不安全的
详情请查看https://www.ibm.com/developerworks/cn/java/j-jodatime.html
Java8日期时间的默认格式以下:yyyy-MM-dd-HH-mm-ss.zzz
几个主要的核心类:
2018-01-14T02:20:13.592Z
下面看看这些类具体如何使用
LocalDate是不变的日期时间对象表明一个日期,每每被视为年月日。其余日期字段,如一年中的一天,一周和一周的一天,也能够访问。例如,“2007年10月2日”的值能够被存储在一个LocalDate。
LocalTime是不变的日期时间对象表明一个时间,每每被视为小时分钟秒。时间为表明的纳秒级精度。例如,值“13:45.30.123456789”能够存储在一个LocalTime。
LocalDateTime是不变的日期时间对象表明一个日期时间,每每被视为年、月、日、时、分、秒。其余日期和时间字段,如一年中的一天,一周和一周的一天,也能够访问。时间为表明的纳秒级精度。例如,值“2007年10月2日在13:45.30.123456789”能够存储在一个LocalDateTime。
//now()在默认时区中从系统时钟获取当前日期。 LocalDate today = LocalDate.now(); LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); //等价于 today.plusWeeks(1) //of(int year, int month, int dayOfMonth) 得到 LocalDate实例从一年、月、日。 LocalDate date = LocalDate.of(2019,5,31); LocalTime time = LocalTime.of(20,31,20); //of(LocalDate date, LocalTime time) 得到 LocalDateTime实例的日期和时间。 LocalDateTime dateTime = LocalDateTime.of(date,time); System.out.println(dateTime); //LocalDate结合LocalTime成一个LocalDateTime LocalDateTime dateTime2 = date.atTime(time); System.out.println(dateTime2); //2019-05-31T20:31:20
格式器用于解析日期字符串和格式化日期输出,建立格式器最简单的方法是经过 DateTimeFormatter 的静态工厂方法以及常量。建立格式器通常有以下三种方式:
和旧的 java.util.DateFormat 相比较,全部的 DateTimeFormatter 实例都是线程安全的。
使用DateTimeFormatter完成格式化
//获取默认时区中从系统时钟获取当前日期时间。 LocalDateTime localDateTime = LocalDateTime.now(); //建立一个格式化程序使用指定的模式。 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatDateTime = localDateTime.format(formatter); System.out.println(formatDateTime); //DateTimeFormatter提供了一些默认的格式化器,DateTimeFormatter.ISO_LOCAL_DATE_TIME 格式 yyyy-MM-ddTHH:mm:ss.SSS String dateTime2 = localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); System.out.println(dateTime2);
使用DateTimeFormatter完成解析字符串
//得到 LocalDate实例,从使用特定格式的文本字符串解析,文字使用格式化程序解析,返回一个日期。 LocalDate localDate = LocalDate.parse("2018/11/11",DateTimeFormatter.ofPattern("yyyy/MM/dd")); System.out.println(localDate); //2018-11-11
Instant 表示时间线上的一点(与 Date 相似),它只是简单地表示自 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC)开始的秒数。
Instant 由两部分组成,一是从原点开始到指定时间点的秒数 s, 二是距离该秒数 s 的纳秒数。它以 Unix 时间戳的形式存储日期时间,不提供处理人类意义上的时间单位(年月日等)。
你能够经过Instant类的工厂方法建立一个Instant实例
//调用instant.now()来建立一个确切的表达当前时间的Instant对象.另外也有一些其它方法能建立Instant,具体请查阅Java官方文档。 Instant now = Instant.now(); Instant later = now.plusSeconds(3); Instant earlier = now.minusSeconds(3); //第一个参数是秒,第二个是纳秒参数,纳秒的存储范围是0至999,999,999 //2s以后的在加上100万纳秒(1s) Instant instant = Instant.ofEpochSecond(2,1000000000); System.out.println(instant); //1970-01-01T00:00:03Z Instant instant1 = Instant.now(); System.out.println(instant1); //2019-05-31T16:19:28.719Z Instant instant2 = Instant.parse("2018-11-11T10:12:35.342Z"); System.out.println(instant2); //2018-11-11T10:12:35.342Z //java.util.Date与Instant可相互转换 Instant timestamp = new Date().toInstant(); Date.from(Instant.now()); //为了更好的显示,代码改写为 Date date = new Date(); Instant timestamp = date.toInstant(); System.out.println(date); System.out.println(timestamp); Instant now1 = Instant.now(); Date date1 = Date.from(now1); System.out.println(now1); System.out.println(date1); //输出结果 Sat Jun 01 00:29:42 GMT+08:00 2019 2019-05-31T16:29:42.566Z 2019-05-31T16:29:42.588Z Sat Jun 01 00:29:42 GMT+08:00 2019
Clock用于查找当前时刻,能够用来获取某个时区下当前的日期和时间,也能够用来代替旧的System.currentTimeMillis()方法和TimeZone.getDefault()方法。
//返回系统默认时间 Clock clock = Clock.systemDefaultZone(); System.out.println(clock.instant().toString()); //世界协调时UTC Clock clock = Clock.systemUTC(); //经过Clock获取当前时刻 System.out.println("当前时刻为:" + clock.instant()); //获取clock对应的毫秒数,与System.currentTimeMillis()输出相同 System.out.println(clock.millis()); System.out.println(System.currentTimeMillis());
一个Duration实例是不可变的,当建立出对象后就不能改变它的值了。你只能经过Duration的计算方法,来建立出一个新的Durtaion对象。你会在以后的教程中见到的。一个Duration对象表示两个Instant间的一段时间。
建立Duration实例,使用Duration类的工厂方法来建立一个Duration对象
Instant first = Instant.now(); // wait some time while something happens Instant second = Instant.now(); Duration duration = Duration.between(first, second); //得到Duration表示秒数,而后得到在此期间的分钟数、小时数、天数 Duration d = Duration.ofSeconds(6000); System.out.println("6000秒至关于" + d.toMinutes() + "分"); System.out.println("6000秒至关于" + d.toHours() + "小时"); System.out.println("6000秒至关于" + d.toDays() + "天");
访问Duration的时间
一个Duration对象里有两个域:纳秒值(小于一秒的部分),秒钟值(一共有几秒),他们的组合表达了时间长度。注意与使用System.getCurrentTimeMillis()时不一样,Duration不包含毫秒这个属性。
你能够经过如下两个方法获得它们的值:getSeconds()和getNano()
Period 是以年月日来衡量一个时间段,用于计算两个日期间隔,因此 between() 方法只能接收 LocalDate 类型的参数。
LocalDate start = LocalDate.of(2018, Month.JANUARY, 1); LocalDate end = LocalDate.of(2020, Month.NOVEMBER, 11); System.out.println("相隔月数:"+Period.between(start, end).getMonths()); System.out.println("相隔天数:"+Period.between(start, end).getDays()); //输出结果 相隔月数:10 相隔天数:10
值得注意的是,Period 获得的是差值的绝对值(对应年月日直接计算数学上的差值),而并不表示真正的区间距离。
long distanceMonth = start.until(end, ChronoUnit.MONTHS); long distanceDay= start.until(end, ChronoUnit.DAYS); System.out.println("相隔月数"+distanceMonth); System.out.println("相隔天数"+distanceDay); //输出结果 相隔月数:34 相隔天数:1045
ZonedDateTime类是Java 8中日期时间功能里,用于表示带时区的日期与时间信息的类。ZonedDateTime 类的值是不可变的,因此其计算方法会返回一个新的ZonedDateTime 实例。
Java 使用 ZoneId 来标识不一样的时区,从基准 UTC 开始的一个固定偏移。
建立一个ZonedDateTime实例
//使用当前时间做为值新建对象 ZonedDateTime dateTime = ZonedDateTime.now(); //使用指定的年月日、时分、纳秒以及时区ID来新建对象 //时区是用ZoneId类表示的,可使用ZoneId.now()或ZoneId.of(“xxx”)来实例化: //传给of()方法的参数是时区的ID,如“UTC+1”指距离UTC(格林威治时间)有一小时的时差 ZoneId zoneId = ZoneId.of("UTC+1"); ZonedDateTime dateTime2 = ZonedDateTime.of(2019, 6, 1, 14, 40, 48, 1234, zoneId); //也可使用另外一种方式表示zone id,即便用地区名字 ZoneId zoneId2 = ZoneId.of("Europe/Copenhagen"); //GregorianCalendar与ZonedDateTime相互转换 ZonedDateTime zonedDateTime = new GregorianCalendar().toZonedDateTime(); GregorianCalendar.from(zonedDateTime);
有的时候,你须要进行一些更加复杂的操做,好比,将日期调整到下个周日、下个工做日,或者是本月的最后一天。
简单应用例子
LocalDate localDate = LocalDate.now(); // 1. 本月第一天 LocalDate firstDayOfMonth = localDate.with(TemporalAdjusters.firstDayOfMonth()); // 2. 本月最后一天 LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth()); // 3. 本年第一天 LocalDate firstDayOfYear = localDate.with(TemporalAdjusters.firstDayOfYear()); // 4. 下个月第一天 LocalDate firstDayOfNextMonth = localDate.with(TemporalAdjusters.firstDayOfNextMonth()); // 5. 本年度最后一天 LocalDate lastDayOfYear = localDate.with(TemporalAdjusters.lastDayOfYear()); System.out.println(firstDayOfMonth); System.out.println(lastDayOfMonth); System.out.println(firstDayOfYear); System.out.println(firstDayOfNextMonth); System.out.println(lastDayOfYear);
这时,你可使用重载版本的with方法,向其传递一个提供了更多定制化选择的TemporalAdjuster对象,更加灵活地处理日期。TemporalAdjusters类经过静态方法提供了大量的经常使用的TemporalAdjuster的实现供咱们使用。
/** * 时间校订器TemporalAdjuster */ @Test public void Test() { LocalDateTime now1 = LocalDateTime.now(); //获取月中的第一天 now1.with(TemporalAdjusters.firstDayOfMonth()); //获取下一年的第一天 now1.with(TemporalAdjusters.firstDayOfNextYear()); //获取年中第一天 now1.with(TemporalAdjusters.lastDayOfYear()); //获取月中最后一天 now1.with(TemporalAdjusters.lastDayOfMonth()); //获取下个星期一 now1.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); //自定时时间:下一个工做日,由于这里须要一个接口,因此彻底能够自定义方法 now1.with((e) -> { LocalDateTime now = (LocalDateTime)e; DayOfWeek dow = now.getDayOfWeek(); if (dow.equals(DayOfWeek.FRIDAY)) return now.plusDays(3); else if (dow.equals(DayOfWeek.SATURDAY)) return now.plusDays(2); return now.plusDays(1); }); }
将Date转换为LocalDate,LocalTime,LocalDateTime能够借助于ZonedDateTime和Instant,实现以下:
Date date = new Date(); System.out.println("current date: " + date); // Date -> LocalDateTime LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); System.out.println("localDateTime by Instant: " + localDateTime); // Date -> LocalDate LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); System.out.println("localDate by Instant: " + localDate); // Date -> LocalTime LocalTime localTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime(); System.out.println("localTime by Instant: " + localTime); //2. Date -> LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); System.out.println("localDateTime by ofInstant: " + localDateTime);
因为JDK8实现了向下兼容,因此Date里在JDK8版本引入了2个方法,from和
toInstant,因此咱们能够借助这两个方法来实现LocalDateTime到Date的转换。将LocalDateTime转为Date以下:
LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime); // LocalDateTime -> Date Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); System.out.println("LocalDateTime -> current date: " + date); // LocalDate -> Date,时间默认都是00 LocalDate localDate = LocalDate.now(); date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); System.out.println("LocalDate -> current date: " + date);
经过LocalDate,LocalTime,LocalDateTime的parse方法和DateTimeFormatter来实现:
//字符串->日期 LocalDate localDate = LocalDate.parse("2018-09-09", DateTimeFormatter.ofPattern("yyyy-MM-dd")); LocalDateTime localDateTime = LocalDateTime.parse("2018-09-10 12:12:12", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); //日期->字符串 String localDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); String localDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // 也能够经过DateTimeFormatter的format方法 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); localDateTime = dateTimeFormatter.format(LocalDateTime.now());
具体实现以下:
//时间戳->LocalDateTime public static LocalDateTime convertToDate(long timestamp) { // ofEpochSecond 以秒为单位, ofEpochMilli 以毫秒为单位 // Instant.ofEpochSecond(timestamp); Instant instant = Instant.ofEpochMilli(timestamp); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); } //LocalDateTime->时间戳 public static long convertToTimestamp() { LocalDateTime localDateTime = LocalDateTime.now(); return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); }
更多方法使用请参考Java api文档
参考文章:
http://www.importnew.com/14140.html
https://docs.oracle.com/javase/8/docs/api/
https://www.jianshu.com/p/f4abe1e38e09