Java格式化与日期时间简介

目录

格式化符

指定格式化参数

时间日期

格式化

SimpleDateFormat格式化

DateTimeFormatter格式化

传统方式%t*

LocalDate

LocalTime

LocalDateTime

时区

时间点Instant

时间差Duration

与时间戳转换


Java中的格式化类似C语言中printf,如System.out.printf(...)String.format(...)等。

格式化符

格式化符以%开始,根据格式化符格式化后面的参数。

可使用各种标志来控制格式化输出

指定格式化参数

可以使用%n$(n为参数位置,从1开始,后跟$符)指定所要格式化的参数。
也可以使用<标志,指示前面格式说明中的参数被再次使用。

System.out.printf("%1$s %2$tF %2$tT", "Now:", new Date());
System.out.printf("%s %tF %<tT", "Now:", new Date());
// Now: 2020-02-26 23:02:25

时间日期

Java8中引入java.time API,修正早期Date类中的一些缺陷。

获取当前时间:

  • Instant.now()
  • LocalDateTime.now()

 

格式化

SimpleDateFormat与Java8中引入的DateTimeFormatter(`ofPattern`)都可方便自定义格式化符,常用的格式化符号:

  • 年:yyyy/yy

  • 月:MM/M

  • 日:dd/d

  • 小时(24):HH/H

  • 小时(12):KK/K

  • 显示AMPM:a

  • 分钟:mm

  • 秒:ss

  • 纳秒:nnnnnn

  • 星期几:e:3;E:Wed;EEEE:Wednesday

 

SimpleDateFormat格式化

Date date = new Date();
String strDateFormat = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
System.out.println(sdf.format(date));

 

DateTimeFormatter格式化

java.time.format.DateTimeFormatter被设计用来替代java.util.DateFormat。使用ofPattern可以自定义格式方式。

LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 2020-02-27T22:29:18.105

DateTimeFormatter dtFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
System.out.println(dtFormat.format(today));
// 2020-02-27 22:29

传统方式%t*

在printf中可以使用%t*(t后面跟一个字符)来格式化时间,但推荐使用java.time包中的方法。

 

LocalDate

使用LocalDate来表示本地日期

LocalTime

使用LocalTime来表示本地时间

LocalDateTime

表示日期和时间的LocalDateTime类,用于存储固定时区的时间点;若要带时区,需要使用ZonedDateTime类。

LocalDateTime转Unix时间戳:

  • 秒级:结合时区信息转换为ZonedDateTime(atZone、atOffset),然后转换为秒级的Unix时间戳;
  • 毫秒级:先转换为ZonedDateTime,然后再转换为Instant,后转为Unix时间戳;

 

时区

ZonedDateTime等需要时区,Java中有TimeZone、ZoneOffset等表示时区;可通过如下方式获取当前时区信息与时区偏移:

TimeZone defZone = TimeZone.getDefault();
ZoneId defId = defZone.toZoneId();
int offsetMilli = defZone.getOffset(System.currentTimeMillis());
Duration dur = Duration.ofMillis(offsetMilli);
ZoneOffset defOffset = ZoneOffset.ofHours((int) dur.toHours());
System.out.printf("Zone: %s \nId: %s \noffset: %s\n", defZone, defId, defOffset);

// Zone: sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null] 
// Id: Asia/Shanghai 
// offset: +08:00

 

时间点Instant

Instant类代表的是某个时间,精确到纳秒。可方便地与Unix时间戳进行转换:

  • ofEpochMilli、ofEpochSecond:Unix时间戳转Instant
  • toEpochMilli:Instant转Unix时间戳

引入Instant表示时间点,通过Instant.now()获取当前时刻;Duration表示时刻间的时间量:

 

时间差Duration

Duration表示时间差:

  • between:可方便地计算两个时间点间的差值;
  • ofXXX:可方便的把天、时、分、秒、毫秒等转换为Duration;
  • toXXX:把Duration转换为对应天、时、分、毫秒(秒通过getSeconds),注意:获取的是总数(如Duration.ofDays(1)转换后分别为:1天、24小时、24*60分...)
Instant start = Instant.now();
try {
    Thread.sleep(1500);
} catch (Exception ex) {
    ex.printStackTrace();
}
Instant end = Instant.now();

Duration elapse = Duration.between(start, end);
System.out.printf("Second: %d, Mill: %d", elapse.getSeconds(), elapse.toMillis());
// Second: 1, Mill: 1500

因Duration默认获取的时分秒都是整体,要分别获取(类似 H:M:S),则需要自己处理:

Duration durParse = Duration.parse("P1DT2H3M4.5678S");
System.out.printf("%dD %dH:%dM:%dS\n",
        durParse.toDays(),
        durParse.minusDays(durParse.toDays()).toHours(),
        durParse.minusHours(durParse.toHours()).toMinutes(),
        durParse.minusMinutes(durParse.toMinutes()).getSeconds()
        );
System.out.println(durParse);


// 1D 2H:3M:4S
// PT26H3M4.5678S

 

与时间戳转换

​LocalDateTime可方便地与时间戳(转换为UTC时候后,从1970年01月01日00时00分00秒到此时间的秒数)转换,转换时需要提供时区信息(表示此时间是哪个时区):

DateTimeFormatter fmtTime = DateTimeFormatter.ofPattern("yyyy-M-d H:m:s");
String strTime = "2021-6-17 9:15:01";
LocalDateTime dtTime = LocalDateTime.parse(strTime, fmtTime);

// As UTC time
long nMillUTC = dtTime.toInstant(ZoneOffset.UTC).toEpochMilli();
long nSecondUTC = dtTime.toEpochSecond(ZoneOffset.UTC);
System.out.printf("AS UTC: Milli-%d, Second-%d \n", nMillUTC, nSecondUTC);

// As Local time
long nMillLocal = dtTime.atOffset(ZoneOffset.of("+8")).toInstant().toEpochMilli();
long nSecondLocal = dtTime.atZone(ZoneId.systemDefault()).toEpochSecond();
System.out.printf("AS Local: Milli-%d, Second-%d %n", nMillLocal, nSecondLocal);

LocalDateTime dtUTC = LocalDateTime.ofEpochSecond(nSecondUTC, 0, ZoneOffset.UTC);
// LocalDateTime dtUTCAsLocal = Instant.ofEpochSecond(nSecondUTC).atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();
LocalDateTime dtUTCAsLocal = Instant.ofEpochSecond(nSecondUTC).atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime dtLocal = Instant.ofEpochMilli(nMillLocal).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(dtUTC);
System.out.println(dtUTCAsLocal);
System.out.println(dtLocal);

// AS UTC: Milli-1623921301000, Second-1623921301     对应北京时间:2021-06-17 17:15:01
// AS Local: Milli-1623892501000, Second-1623892501   对应北京时间:2021-06-17 09:15:01
// 2021-06-17T09:15:01
// 2021-06-17T09:15:01
// 2021-06-17T09:15:01

把time作为本地时间(北京时间)转换时,比作为UTC时间转换时小8个小时;因为作为本地时间时,需要先转换为UTC时间(减8小时)后再转。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值