目录
1.3 java.text.SimpleDateFormat类
2.1 LocalDate、LocalTime、LocalDateTime
2.3 格式化与解析日期或时间DateTimeFormatter类
3. DecimalFormat和NumberFormat等
JDK8之前日期时间API的继承树
System类提供的public static long currentTimeMillis()用来返回当前时 间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
此方法适于计算时间差。
计算世界时间的主要标准有:
UTC(Coordinated Universal Time)
GMT(Greenwich Mean Time)
CST(Central Standard Time)
表示特定的瞬间,精确到毫秒
构造器:
Date():使用无参构造器创建的对象可以获取本地当前时间。
Date(long date)
常用方法:
getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat),zzz是时间标准。
其它很多方法都过时了。
Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat 类是一个不与语言环境有关的方式来格式化和解析日期的具体类。
它允许进行格式化:日期==>文本、解析:文本==>日期
格式化:
SimpleDateFormat() :默认的模式和语言环境创建对象
public SimpleDateFormat(String pattern):该构造方法可以用参数pattern 指定的格式创建一个对象,该对象调用
public String format(Date date):方法格式化时间对象date
解析:
public Date parse(String source):从给定字符串的开始解析文本,以生成 一个日期。
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
获取Calendar实例的方法
使用Calendar.getInstance()方法
调用它的子类GregorianCalendar的构造器
一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想 要的时间信息。比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY 、 MINUTE、SECOND
public void set(int field,int value)
public void add(int field,int amount)
public final Date getTime()
public final void setTime(Date date)
注意:获取月份时:一月是0,二月是1,以此类推,12月是11;获取星期时:周日是1,周二是2 ,... ,周六是7
- package com.openlab.day16;
-
- import java.text.DateFormat;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Calendar;
- import java.util.Date;
-
- import org.junit.jupiter.api.Test;
-
- class TestDate {
-
- @Test
- void test() {
- // java.util.Date类,用来创建时间和日期
- // 如果调用默认的没有参数的构造函数,
- // 则创建的当前时间
- Date date = new Date();
-
- // 1970年
- // Date date = new Date(0L);
-
- // 注意,不建议使用如下的一些构造
- // Date date = new Date("1980/02/02");
- // Date date = new Date(100, 02, 03);
- // Date date = new Date(100, 02, 03, 12, 23);
- // Date date = new Date(100, 02, 03, 12, 23, 59);
-
- System.out.println(date);
- // System.err.println(date.getYear());
- // System.err.println(date.getMonth());
- // System.err.println(date.getDate());
- // System.err.println(date.getDay());
-
- // date.setHours(14);
- // System.out.println(date);
-
- // 时间戳(邮戳),计算机中时间就是数字
- System.out.println(date.getTime());
- // Asia/Shanghai
-
- // 获取系统当前时间戳,毫秒数
- System.err.println(System.currentTimeMillis());
- // 获取系统当前时间戳, 纳秒数
- System.err.println(System.nanoTime());
- }
-
- @Test
- void testFormatDate() {
- // 用来格式化日期的格式化对象
- DateFormat dateFormat = new SimpleDateFormat("Gyyyy年MM月dd日 HH:mm:ss");
- Date date = new Date();
-
- // 将时间对象(Java对象)转换为需要的字符串格式
- String strDate = dateFormat.format(date);
- System.out.println(strDate);
- }
-
- @Test
- void testFormatDate02() {
- // 页面传递过来时间,字符串来描述的
- /**
- * 在高并发场景下,SimpleDateFormat是一个非线程安全类
- * 在高并发场景下,不建议使用SimpleDateFormat,如果一定要是用,建议加锁操作
- * JDK为了解决这些问题,在jdk8.0之后,
- * 专门设计了一套新的API用来解决高并发场景下的时间操作问题
- */
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- String strDate = "2020-03-08 18:59:22";
-
- // 将特定时间字符串转换为时间对象
- Date date = null;
- try {
- date = dateFormat.parse(strDate);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- System.out.println(date);
- }
-
- @Test
- void testCalendar() {
- // 日历类
- Calendar calendar = Calendar.getInstance();
- // 获取当前时间以及相关常数
- System.out.println(calendar.get(Calendar.YEAR));
- System.out.println(calendar.get(Calendar.MONTH));
- System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
- System.out.println(calendar.get(Calendar.HOUR));
- }
- }
如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不 过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了 一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用 了。而Calendar并不比Date好多少。它们面临的问题是:
可变性:像日期和时间这样的类应该是不可变的。
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date有用,Calendar则不行。
此外,它们也不是线程安全的;不能处理闰秒等。
总结:对日期和时间的操作一直是Java程序员最痛苦的地方之一
JDK8,吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。 新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间 (LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime) 和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法, 用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简 化了日期时间和本地化的管理。
说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽 管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一
LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例 是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。 它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区 相关的信息。
LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
LocalTime表示一个时间,而不是日期。
LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一。
注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示 法,也就是公历
方法 | 说明 |
---|---|
now() / * now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHour()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
withDayOfMonth()/withDayOfYear()/ withMonth()/withYear() | 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 |
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、几周、几个月、几年、几小时 |
minusMonths() / minusWeeks()/ minusDays()/minusYears()/minusHours() | 从当前对象减去几月、几周、几天、几年、几小时 |
Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中, 也是从1970年开始,但以毫秒为单位。
java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间 单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。 概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒 数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级
(1 ns = 10-9 s) 1秒 = 1000毫秒 =10^6微秒=10^9纳秒
方法 | 描述 |
---|---|
now() | 静态方法,返回默认UTC时区的Instant类的对象 |
ofEpochMilli(long epochMilli) | 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒 数之后的Instant类的对象 |
atOffset(ZoneOffset offset) | 结合即时的偏移来创建一个 OffsetDateTime |
toEpochMilli() | 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳 |
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01 日08时00分00秒)起至现在的总秒数
java.time.format.DateTimeFormatter 类,该类提供了三种格式化方法
预定义的标准格式。如: ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
方 法 | 描 述 |
---|---|
ofPattern(String pattern) | 静态方法 , 返 回 一 个 指 定 字 符 串 格 式 的 DateTimeFormatter |
format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、时间 |
- package com.openlab.day16;
-
- import java.time.Instant;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- import java.time.LocalTime;
- import java.time.Month;
- import java.time.format.DateTimeFormatter;
-
- import org.junit.jupiter.api.Test;
-
- public class Testjdk8DateTime {
-
- @Test
- void testLocalDate() {
- // LocalDate 是获取当前本地日期对象
- LocalDate now = LocalDate.now();
- System.out.println(now);
-
- // 使用of方法获取对应时间的日期对象
- // LocalDate date = LocalDate.of(2020, 3, 4);
- LocalDate date = LocalDate.of(2020, Month.MARCH, 4);
- System.out.println(date);
-
- // 使用字符串时间格式创建日期对象
- LocalDate date2 = LocalDate.parse("2020-08-23");
- System.out.println(date2);
- }
-
- @Test
- void testLocalDate02() {
- // LocalDate 是获取当前本地日期对象
- LocalDate now = LocalDate.now();
- System.out.println(now.getYear());
- System.out.println(now.getMonthValue());
- System.out.println(now.getDayOfMonth());
- }
-
- @Test
- void testLocalTime() {
- LocalTime now = LocalTime.now();
- System.out.println(now);
-
- LocalDateTime now2 = LocalDateTime.now();
- System.out.println(now2);
- }
-
- @Test
- void testLocalTimeFormatter() {
- LocalDateTime now2 = LocalDateTime.now();
- System.out.println(now2);
-
- DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
- String strDate = now2.format(pattern);
- System.out.println(strDate);
-
- LocalDateTime localDateTime = LocalDateTime.parse("2016年03月04日 12:12:12", DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
- System.out.println(localDateTime);
-
- }
-
- @Test
- void testInstant() {
- // 格林威治标准时间
- Instant now = Instant.now();
- System.out.println(now);
- }
- }
ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris
ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12- 03T10:15:30+01:00 Europe/Paris。
其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如: Asia/Shanghai等
Clock:使用时区提供对当前即时、日期和时间的访问的时钟。
持续时间:Duration,用于计算两个“时间”间隔
日期间隔:Period,用于计算两个“日期”间隔
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整 到“下一个工作日”等操作。
TemporalAdjusters : 该类通过静态方法 (firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用 TemporalAdjuster 的实现。
- // ZoneId:类中包含了所有的时区信息
- // ZoneId的getAvailableZoneIds():获取所有的ZoneId
- Set
zoneIds = ZoneId.getAvailableZoneIds(); - for (String s : zoneIds) {
- System.out.println(s);
- }
- // ZoneId的of():获取指定时区的时间
- LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
- System.out.println(localDateTime);
- //ZonedDateTime:带时区的日期时间
- // ZonedDateTime的now():获取本时区的ZonedDateTime对象
- ZonedDateTime zonedDateTime = ZonedDateTime.now();
- System.out.println(zonedDateTime);
- // ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象
- ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
- System.out.println(zonedDateTime1);
-
- //Duration:用于计算两个“时间”间隔,以秒和纳秒为基准
- LocalTime localTime = LocalTime.now();
- LocalTime localTime1 = LocalTime.of(15, 23, 32);
- //between():静态方法,返回Duration对象,表示两个时间的间隔
- Duration duration = Duration.between(localTime1, localTime);
- System.out.println(duration);
- System.out.println(duration.getSeconds());
- System.out.println(duration.getNano());
- LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
- LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
- Duration duration1 = Duration.between(localDateTime1, localDateTime);
- System.out.println(duration1.toDays());
-
- //Period:用于计算两个“日期”间隔,以年、月、日衡量
- LocalDate localDate = LocalDate.now();
- LocalDate localDate1 = LocalDate.of(2028, 3, 18);
- Period period = Period.between(localDate, localDate1);
- System.out.println(period);
- System.out.println(period.getYears());
- System.out.println(period.getMonths());
- System.out.println(period.getDays());
- Period period1 = period.withYears(2);
- System.out.println(period1);
-
- // TemporalAdjuster:时间校正器
- // 获取当前日期的下一个周日是哪天?
- TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
- LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
- System.out.println(localDateTime);
- // 获取下一个工作日是哪天?
- LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
- @Override
- public Temporal adjustInto(Temporal temporal) {
- LocalDate date = (LocalDate) temporal;
- if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
- return date.plusDays(3);
- } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
- return date.plusDays(2);
- } else {
- return date.plusDays(1);
- }
- }
- });
- System.out.println("下一个工作日是:" + localDate);
在工作当中,可能经常会遇到比如数据保留两位小数显示,去除后面多余0,按指定格式输出数据这种需求,有时隔得时间久了也难免会忘记,Java提供一个工具类NumberFormat。
NumberFormat 是所有数值格式的抽象基类。此类提供格式化和解析数值的接口。NumberFormat 还提供了一些方法来确定哪些语言环境具有数值格式,以及它们的名称是什么
NumberFormat 可用于格式化和解析任何语言环境的数值。使代码能够完全独立于小数点、千位分隔符甚至所用特定小数位数的语言环境约定,并与数值格式是否为偶小数无关
数值格式化
getInstance()、getNumberInstance():返回当前默认语言环境的通用数值格式。
getInstance(Locale)、getNumberInstance(Locale):返回指定语言环境的通用数值格式。
NumberFormat.setMinimumIntegerDigits(int):设置数的整数部分所允许的最小位数。
NumberFormat.setMaximumIntegerDigits(int):设置数的整数部分所允许的最大位数。
NumberFormat.setMinimumFractionDigits(int):设置最少小数点位数,不足的位数以0补位,超出的话按实际位数输出。
NumberFormat.setMaximumFractionDigits(int):设置最多保留小数位数,不足不补0。
NumberFormat.getCurrencyInstance(Locale):返回指定语言环境的通货数值格式
NumberFormat.getPercentInstance():设置数的百分比形式
- @Test
- void testNumberFormat() {
- // 货币、百分比……
- NumberFormat currencyInstance = NumberFormat.getCurrencyInstance();
- System.out.println(currencyInstance.format(123456)); // ¥123,456.00
- }
-
- @Test
- void testNumberFormat02() {
- // 货币、百分比……
- // NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(Locale.US);
- // NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(Locale.UK);
- // NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(Locale.FRANCE);
- NumberFormat currencyInstance = NumberFormat.getCurrencyInstance(Locale.GERMAN);
- System.out.println(currencyInstance.format(123456)); // ¤ 123.456,00
- }
-
- @Test
- void testNumberFormat03() {
- // 千分位分隔符
- NumberFormat currencyInstance = NumberFormat.getNumberInstance();
- System.out.println(currencyInstance.format(123456)); // 123,456
- }
-
- @Test
- void testNumberFormat04() {
- // 货币、百分比……
- NumberFormat currencyInstance = NumberFormat.getPercentInstance();
- System.out.println(currencyInstance.format(1.23456)); // 123%
- }
DecimalFormat 是 NumberFormat 的一个具体子类,用于格式化十进制数字
DecimalFormat 类主要靠 # 和 0 两种占位符号来指定数字长度。
0 表示如果位数不足则以 0 填充,
# 表示只要有可能就把数字拉上这个位置。
如果你想了解更多,请参考 DecimalFormat 类的文档
- @Test
- void testDecimalFormat() {
- double num = 23465.1264566;
-
- // 主要是在.之后,表示要保留的小数位
- DecimalFormat df = new DecimalFormat("0.0000");
- String format = df.format(num);
- System.out.println(format); // 23465.1265
-
- // 以科学计数法展示数据
- DecimalFormat df2 = new DecimalFormat("0E0");
- System.out.println(df2.format(num)); // 2E4
- }
-
- @Test
- void test06() {
- double pi = 3663.1415927;
- System.out.println(new DecimalFormat("0").format(pi)); // 3663
-
- System.out.println(new DecimalFormat("0.00").format(pi)); // 3663.14
- //取两位整数和三位小数,整数不足部分以0填补。
- System.out.println(new DecimalFormat("00.000").format(pi));// 3663.142
- //取所有整数部分
- System.out.println(new DecimalFormat("#").format(pi)); // 3663
- //以百分比方式计数,并取两位小数
- System.out.println(new DecimalFormat("#.##%").format(pi)); // 366314.16%
- long c = 299792458;
- System.out.println(new DecimalFormat("#.#####E0").format(c));// 2.99792E8
- System.out.println(new DecimalFormat("00.####E0").format(c));// 29.9792E7
-
- System.out.println(new DecimalFormat(",###").format(c));// 299,792,458
-
- System.out.println(new DecimalFormat("光速大小为每秒,###米。").format(c)); // 光速大小为每秒299,792,458米。
- }
- }
Integer类作为int的包装类,能存储的最大整型值为2 31-1,Long类也是有限的, 最大为2 63-1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类 都无能为力,更不用说进行运算了。
java.math包的BigInteger可以表示不可变的任意精度的整数。BigInteger 提供 所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。 另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、 位操作以及一些其他操作。
构造器:BigInteger(String val):根据字符串构建BigInteger对象
常用方法:
public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。
BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟 (this % val) 的两个 BigInteger 的数组。
BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
float、double在运算过程都是需要转换为整数的二进制数据运算
数量非常庞大时,不建议使用float或者double,而是使用更加精确的decimal类型
一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中, 要求数字精度比较高,故用到java.math.BigDecimal类。
BigDecimal类支持不可变的、任意精度的有符号十进制定点数
构造器:
public BigDecimal(double val)
public BigDecimal(String val)
常用方法
public BigDecimal add(BigDecimal augend)
public BigDecimal subtract(BigDecimal subtrahend)
public BigDecimal multiply(BigDecimal multiplicand)
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
- @Test
- void testBigDecimal() {
- // float、double在运算过程都是需要转换为整数的二进制数据运算
- System.out.println(0.1 + 0.2 == 0.3); // false
-
- // 数量非常庞大时,不建议使用float或者double
- // 而是使用更加精确的decimal类型
- // BigDecimal num1 = new BigDecimal(0.1);
- // BigDecimal num2 = new BigDecimal(0.2);
-
- // 如果不要以整数的形式操作,可以使用字符串
- BigDecimal num1 = new BigDecimal("0.1");
- BigDecimal num2 = new BigDecimal("0.2");
- System.out.println(num1.add(num2)); // 0.3
- }