细谈Java中的时间与日期
Posted polygon-live
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了细谈Java中的时间与日期相关的知识,希望对你有一定的参考价值。
Data类
java.util.Date类实在Java之中获得日期时间操作的最简单的一个程序类,这个类可以直接通过实例化Date类对象的形式获取当前的日期时间。
范例:获取当前的日期时间
import java.util.Date; public class Demo { public static void main(String args[]) { System.out.println(new Date()); } } |
|
程序执行结果: |
Fri Mar 27 19:12:56 CST 2020 |
Date 里面给出的日期时间默认格式采用的是外国人的习惯,虽然中国人民不习惯,但是里面包含有正确的信息,如果想要进行更加详细的处理,后面会有专门的类,除了以上的构造方法之外,在整个的Date类里面也提供有如下的操作方法。
No. |
方法名称 |
类型 |
描述 |
01 |
Public Date() |
普通 |
获取当前的日期时间对象 |
02 |
Public Date(long date) |
普通 |
将时间戳数字转为Date类对对象 |
03 |
Public long getTime() |
普通 |
将日期时间以long数据类型的形式返回 |
04 |
public boolean after?(Date when) |
普通 |
是否在指定日期时间之后 |
05 |
public boolean before?(Date when) |
普通 |
是否在指定的日期时间之前 |
在Java程序里面,日期时间、内存大小或者文件大小都是用long数据类型来进行描述(毫秒数),在date类里面通过构造方法可以接受一个long日期时间的数字,也可以通过Date返回一个long的数据类型。如果想要清楚的理解Date类之中两个构造彼此之间的关系,最佳的做法还是需要浏览一下Date类的构造方法源代码。
【构造方法】Public Date() |
【构造方法】Public Date(long date) |
public Date() { this(System.currentTimeMillis()); } |
public Date(long date) { fastTime = date; } private transient long fastTime; |
所谓的无参构造方法实际上会自动进行单参构造的调用,并且传递的参数也是System类之中所获得的当前的日期时间的数值。
下面来研究一下long与Date类之间的转换。
范例:观察long与Date类之间的转换操作:
import java.util.Date; publicclass Demo { publicstaticvoid main(String args[]) { longdateTime = System.currentTimeMillis() - 10000; //得到一个long数据类型 Date DateA = new Date(dateTime); // long转化为Date类型 Date DateB = new Date(); System.out.println(DateA); System.out.println(DateB); System.out.println("两个日期间的毫秒数:" + (DateB.getTime() - DateA.getTime())); System.out.println("【先后关系】AFTER:" + (DateA.after(DateB))); System.out.println("【先后关系】BEFORE:" + (DateA.before(DateB))); } } |
|
程序执行结果: |
Sun Mar 29 13:41:57 CST 2020 两个日期间的毫秒数:10005 //10005是因为程序执行操作时间不定,应该为10000 【先后关系】AFTER:false 【先后关系】BEFORE:true |
通过此时的程序代码的执行可以得到如下两个重要信息:日期时间和long之间的转换、Date类可以实现日期先后关系的判断。
Calendar类
在Javaz中虽然Date类可以描述日期时间,但是除了日期时间之外的许多关于日历有关从操作,例如:①需要知道某一个日期所在月的最后一天。②判断某一个日期是否处于闰年。对于这些繁琐的日期处理操作。这时候在Java中就可以采用一个java.util.Calendar程序类来完成相应的处理操作,。
观察Calendar类的基本定义:
public abstract class Calendar extends Object implements Serializable, Cloneable, Comparable<Calendar>
|
发现Calendar 类属于抽象类,那么按照原始的概念来理解的话,这个时候应该通过子类进行该对象的实例化,而通过JavaDoc文档可以发现有一个“GregorianCalendar”子类 。
观察Calendar类之中提供的方法。
No. |
方法名称 |
类型 |
描述 |
01 |
public static Calendar getInstance() |
普通 |
获取Calendar类的操作实例 |
02 |
public int get?(int field) |
普通 |
获取成员结构的日期或时间数据 |
03 |
public void set?(int field,int value) |
普通 |
设置指定成员结构的数据内容 |
04 |
public abstract void add?(int field, int amount) |
普通 |
在指定的结构上进行加法计算 |
05 |
|
普通 |
|
06 |
|
普通 |
|
07 |
|
普通 |
|
08 |
|
普通 |
|
09 |
|
普通 |
|
10 |
|
普通 |
|
Calendar类之中的两个构造方法都使用protected方文权限,则意味着这两个构造方法只能够被同一包以及不同包的子类所访问。 如果想要获得本类对象最佳的做法就是通过getInstance()方法完成。
范例:通过Calendar类获取对象实例
import java.util.Calendar;; publicclass Demo { publicstaticvoid main(String args[]) { Calendar calendar = Calendar.getInstance(); //获取对象实例 System.out.println(String.format("当前的日期时间格式: %s-%s-%s %s:%s:%s", calendar.get (calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar .MINUTE), calendar.get(Calendar.SECOND))); } }
|
|
程序执行结果: |
当前的日期时间格式: 2020-3-29 14:30:25 |
但是获取当前的日期时间并不是Calendar的主要作用,这个类主要使用是为了日历的计算。
范例:实现日期的准确计算
import java.util.Calendar;; publicclass Demo { publicstaticvoid main(String args[]) { Calendar calendar = Calendar.getInstance(); //获取对象实例 calendar.add(Calendar.YEAR, 30); //计算30年之后的日期 calendar.add(Calendar.MONTH, 6); //计算半年之后的日期 System.out.println(String.format("当前的日期时间格式: %s-%s-%s %s:%s:%s", calendar.get (calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar .MINUTE), calendar.get(Calendar.SECOND))); } }
|
|
程序执行结果: |
当前的日期时间格式: 2050-9-29 14:38:19 |
如果此时没有采用这样的操作类进行日期的计算处理,二十使用long进行计算,那么所得到的日期时间一定是不准确的。既然Calendar描述的是一个日期结构,就可以考虑进行一些日期上的调用。
范例:找到8月的最后一天
import java.util.Calendar;; publicclass Demo { publicstaticvoid main(String args[]) { Calendar calendar = Calendar.getInstance(); //获取对象实例 calendar.set(calendar.get(calendar.YEAR), 8, 1); //通过9月的第一天来找8月的最后一天 calendar.add(Calendar.DATE, -1); System.out.println(String.format("当前的日期时间格式: %s-%s-%s %s:%s:%s", calendar.get (Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar .MINUTE), calendar.get(Calendar.SECOND))); } } |
|
程序执行结果: |
当前的日期时间格式: 2020-8-31 14:49:52 |
如果想要进行指定日期最后一天的计算操作,就应该定位到指定的日期上,随后在利用一些加减从操作获取日期数据。本范例是先将日期设置到9月的第一天,在利用add()方法在天数上做一个减一操作,就变为了8月的最后一天。
SimpleDateFormat
使用Date类过去日期时间要比使用Calendar类获取的日期时间更加的简单(Calendar类的功能不在于数据的获取,二十在日期的计算上),但是Date类中获取的日期时间不方便阅读。所以在实际项目的开服过程中会存在一种格式化日期的处理操作,而这种处理操作主要依靠的是java.text.SimpleDateFormat类完成。
有如下的中音号的操作方法
No. |
方法名称 |
类型 |
描述 |
01 |
public final String format?(Date date) |
普通 |
将日期格式化为字符串 |
02 |
public Date parse?(String source) throws ParseException |
普通 |
将字符串转化为日期 |
03 |
public SimpleDateFormat?(String pattern) |
普通 |
实例化SimpleDateFormat类对象,并设置匹配模式 |
04 |
|
普通 |
|
05 |
|
普通 |
|
要想成功的对日期进行格式化或者将字符串转化为日期,那么就必须要存在有一个日期时间的匹配表达式,而这组变道时里面最重要的是几个日期时间的单位:年(yyyy)、月(MM)、日(dd)、时(HH)、分(mm)、秒(ss)、毫秒(SSS)。
范例:格式化日期时间(将Date转化为String)
import java.text.SimpleDateFormat; import java.util.Date;; publicclass Demo { publicstaticvoid main(String args[]) { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss.SSS"); //实例化转化类对象 String str = sdf.format(date); //将日期时间转化为字符串 System.out.println(str); } } |
|
程序执行结果: |
2020-03-29-16-59-53.038 |
此时获得的日期时间的字符串信息就符合大家的使用习惯了,采用类似的匹配表达式,也可以实现字符串转为日期时间的处理。
范例:字符串转日期时间(String—>Date)
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;; publicclass Demo { publicstaticvoid main(String args[]) throws ParseException { String str = "2020-03-29-16-59-53.038"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss.SSS"); //实例化转化类对象 Date date = sdf.parse(str); //将日期时间转化为字符串 System.out.println(date); } } |
|
程序执行结果: |
Sun Mar 29 16:59:53 CST 2020 |
在进行项目的开发过程中,在进行数据输入的时候全部的数据信息都是字符串类型,那么就需要依据目标的需求进行数据类型的转换,这样的转化操作会非常常见。
针对实际的开发做出完整的总结:根据给定的结构图形强记下来就可以在实际的项目开发之中进行应用,而这些基本的只是时保证可以编写出项目的基本功。
常见的数据类型转化表
LocalDate类(最新的时间操作类)
在JDK1.8之后的版本中,Java追加了一个新的日期时间的处理包:Java.time,在这个包中提供有三个主要的类型:LocalDate、LocalTime、LocalDateTime。可以通过这些类更加简单的进行日期、时间或日期时间的处理,相比较之前的Calendar类来讲,这些类的使用更加方便。
范例:获取当前的日期时间
import java.text.ParseException; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; publicclass Demo { publicstaticvoid main(String args[]) throws ParseException { LocalDate localDate = LocalDate.now(); //获取当前的日期 LocalTime localTime = LocalTime.now(); //获取当前的时间 LocalDateTime localDateTime = LocalDateTime.now(); //获取当前的日期时间。 System.out.println("【LocalDate实例化对象输出】" + localDate); System.out.println("【LocalTime实例化对象输出】" + localTime); System.out.println("【LocalDateTime实例化对象输出】" + localDateTime); } }
|
|
程序执行结果: |
【LocalDate实例化对象输出】2020-03-29 【LocalTime实例化对象输出】18:20:28.001 【LocalDateTime实例化对象输出】2020-03-29T18:20:28.001 |
可以发现,每一个日期时间类里面都会存在有一个now()方法,这个方法可以直接获取当前系统的日期时间,并且在输出这些对象的时候都可以得到非常明确的信息内容。
在java.time包中最为重要的类是LocalDate类,这个类除了可以直接理工对象的toString()方法获取日期时间之外,也可以针对年、月、日等数据分开获取。
范例:通过LocalDate获取详细的日期数据
import java.text.ParseException; import java.time.LocalDate; import java.time.temporal.ChronoField; publicclass Demo { publicstaticvoid main(String args[]) throws ParseException { LocalDate today = LocalDate.now(); //获取当前的日期 System.out.println(String.format("【当前日期】:%s-%s-%s", today.getYear(),today.getMonthValue(),today.getDayOfMonth())); System.out.println("【获取一周的时间数】" + today.getDayOfWeek().getValue()); System.out.println("【今天是今年的第多少周】" + today.get(ChronoField.ALIGNED_WEEK_OF_YEAR)); System.out.println("【今天是本月的第多少周】" + today.get(ChronoField.ALIGNED_WEEK_OF_MONTH)); System.out.println("【今天是一年的第几天】" + today.getDayOfYear()); } } |
|
程序执行结果: |
【当前日期】:2020-3-29 【获取一周的时间数】7 【今天是今年的第多少周】13 【今天是本月的第多少周】5 【今天是一年的第几天】89 |
同样都属于日期的处理,但是可以明显感觉到通过LocalDate要比直接使用Calendar类处理更加的简单,使用LocalDate还可以非常方便的判断某一个日期所在的年是否为闰年。
范例:判断闰年
import java.text.ParseException; import java.time.LocalDate; publicclass Demo { publicstaticvoid main(String args[]) throws ParseException { LocalDate localDate = LocalDate.parse("1999-04-27"); //操作指定日期 System.out.println("【闰年判断】" + localDate.isLeapYear()); System.out.println("【所处在周几】" + localDate.getDayOfWeek()); } } |
|
程序执行结果: |
【闰年判断】false 【所处在周几】TUESDAY |
在使用LocalDate类进行日期处理的时候,最为强大的功能是可以直接进行日期的计算处理,例如:获得所在月的第一天,或者是最后一天等信息。
范例:通过LocalDate进行日期推算
import java.text.ParseException; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; publicclass Demo { publicstaticvoid main(String args[]) throws ParseException { LocalDate localDate = LocalDate.parse("1999-04-27"); //操作指定日期 System.out.println("【所在月的第一天】" + localDate.with(TemporalAdjusters.firstDayOfMonth())); System.out.println("【所在月的第三天】" + localDate.withDayOfMonth(3)); System.out.println("【所在月的最后一天】" + localDate.with(TemporalAdjusters.lastDayOfMonth())); System.out.println("【300月后的日期】" + localDate.plusMonths(300)); System.out.println("【日期所处月的第一个周一】" + localDate.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); System.out.println("【日期所处年的第一个周一】" + localDate.withMonth(1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); } } |
|
程序执行结果: |
【所在月的第一天】1999-04-01 【所在月的第三天】1999-04-03 【所在月的最后一天】1999-04-30 【300月后的日期】2024-04-27 【日期所处月的第一个周一】1999-04-05 【日期所处年的第一个周一】1999-01-04 |
通过以上的一系列分析之后就可以发现,在进行日期数据的处理上,实际上使用LocalDate类要比直接使用Calendar类更加的简单,同时这个类也属于新时代的类。尽量使用新的技术,old技术迟早会被淘汰
多线程操作下的日期时间格式化
通过前面的学习得到结论:如果想要将日期准华为字符串则肯定要使用SimpleDateFormat类完成,同理,将字符串格式化为日期也一定要使用SimpleDateFormat类,于是这个类几乎就成为了所有项目开发中必然要采用的工具类。
下面来针对于这个工具类的使用进行一些多线程环境下的分析。
范例:观察单一线程下的SimpleDateFormat类的操作
以上是关于细谈Java中的时间与日期的主要内容,如果未能解决你的问题,请参考以下文章