java时间格式转换时时区相关的坑

先上结论:
1、yyyy-MM-dd'T'HH:mm:ss.SSSXXX的XXX表示时区,Z零时区,+08:00东八区(大致)
2、java 8,时间字符串不带时区,使用LocalDateTime,因为即使字符串附带了时区信息也不被使用;如果要使用字符串附带的时区信息则使用ZonedDateTime
3、使用DateTimeFormatter,毫秒都是右补零;SimpleDateFormat是左补零;解决方式使用三位毫秒格式,如:2023-02-13T00:00:00.12Z改为2023-02-13T00:00:00.120Z或2023-02-13T00:00:00.012Z再做数据类型转换

看代码和注释

package com.rootcloud;

import org.apache.commons.lang.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class Main21DateTest {
    public static void main(String[] args) throws ParseException {
        //结论:java 8,时间字符串不带时区,使用LocalDateTime,因为即使字符串附带了时区信息也不被使用;如果要使用字符串附带的时区信息则使用ZonedDateTime
        //使用DateTimeFormatter,毫秒都是右补零;SimpleDateFormat是左补零;解决方式永远使用三位毫秒格式

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); //基准
        System.out.println("2023-02-13T00:00:00.120");
        System.out.println(sdf.parse("2023-02-13T00:00:00.120").getTime());

        System.out.println("DateTimeFormatter+LocalDateTime");
        //XXX代表时区
        final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        //8SH 输入 东八区时间,选择上海时间所在时区,输出 0时区时间,时间戳和基准时间相同(毫秒自动右补零)
        final Instant instant8SH = LocalDateTime.parse("2023-02-13T00:00:00.12+08:00", dateTimeFormatter).atZone(ZoneId.of("Asia/Shanghai")).toInstant();
        System.out.println("8SH");
        System.out.println(instant8SH.toString());
        System.out.println(instant8SH.toEpochMilli());
        //8UTC与8SH相比,输入zoneId变成UTC,输出时间为 0时区2023-02-13T00:00:00.120Z,时间戳比8SH小8H,结论UTC会覆盖+08:00的效果
        final Instant instant8UTC = LocalDateTime.parse("2023-02-13T00:00:00.12+08:00", dateTimeFormatter).atZone(ZoneId.of("UTC")).toInstant();
        System.out.println("8UTC");
        System.out.println(instant8UTC.toString());
        System.out.println(instant8UTC.toEpochMilli());
        //8Default输出和8SH相同,猜测1:覆盖成Asia/Shanghai所在时区,猜测2:不覆盖,使用字符串的时区
        final Instant instant8Default = LocalDateTime.parse("2023-02-13T00:00:00.12+08:00", dateTimeFormatter).atZone(ZoneId.systemDefault()).toInstant();
        System.out.println("8Default");
        System.out.println(instant8Default.toString());
        System.out.println(instant8Default.toEpochMilli());
        //ZUTC 输入Z和UTC同为零时区,输出与基准差8H 符合预期
        final Instant instantZUTC = LocalDateTime.parse("2023-02-13T00:00:00.12Z", dateTimeFormatter).atZone(ZoneId.of("UTC")).toInstant();
        System.out.println("ZUTC");
        System.out.println(instantZUTC.toString());
        System.out.println(instantZUTC.toEpochMilli());
        //ZDefault 与 8Default输出相等,default
        final Instant instantZDefault = LocalDateTime.parse("2023-02-13T00:00:00.12Z", dateTimeFormatter).atZone(ZoneId.systemDefault()).toInstant();
        System.out.println("ZDefault");
        System.out.println(instantZDefault.toString());
        System.out.println(instantZDefault.toEpochMilli());
        //java.time.LocalDateTime.from 里看到有TemporalAccessor有多种实现,其中包括ZonedDateTime,自带时区
        final Instant instant = ZonedDateTime.parse("2023-02-13T00:00:00.12Z", dateTimeFormatter).toInstant();
        System.out.println("ZonedDateTime");
        System.out.println(instant.toString());
        System.out.println(instant.toEpochMilli());
//        报错,必须定义XXX
//        final DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
//        final Instant instant2 = ZonedDateTime.parse("2023-02-13T00:00:00.120", dateTimeFormatter2).toInstant();
//        System.out.println("ZonedDateTime");
//        System.out.println(instant2.toString());
//        System.out.println(instant2.toEpochMilli());

        System.out.println("\nSimpleDateFormat+Date");
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
        Date parse = simpleDateFormat.parse("2023-02-13T00:00:00.12Z");
        System.out.println(parse.getTime());
        parse = simpleDateFormat.parse("2023-02-13T00:00:00.12+08:00");
        System.out.println(parse.getTime());
    }

}



结果:

2023-02-13T00:00:00.120
1676217600120
DateTimeFormatter+LocalDateTime
8SH
2023-02-12T16:00:00.120Z
1676217600120
8UTC
2023-02-13T00:00:00.120Z
1676246400120
8Default
2023-02-12T16:00:00.120Z
1676217600120
ZUTC
2023-02-13T00:00:00.120Z
1676246400120
ZDefault
2023-02-12T16:00:00.120Z
1676217600120
ZonedDateTime
2023-02-13T00:00:00.120Z
1676246400120
ZonedDateTime
2023-02-13T00:00:00.120Z
1676246400120

SimpleDateFormat+Date
1676246400012
1676217600012

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,Java 中可以使用 `SimpleDateFormat` 类来进行日期格式转换。 首先你需要创建一个 `SimpleDateFormat` 对象,并设置好转换的格式,例如: ```java SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ``` 然后,你可以使用 `parse` 方法将字符串类型的日期转换为 `Date` 类型,例如: ```java String dateString = "2022-06-15 15:43:01"; Date date = sdf.parse(dateString); ``` 如果你想将 `Date` 类型的日期转换为字符串类型,可以使用 `format` 方法,例如: ```java Date date = new Date(); String dateString = sdf.format(date); ``` 希望这些信息能够帮到你! ### 回答2: Java提供了一种功能强大的日期格式转换功能,可以方便地将不同格式的日期进行转换。主要是通过SimpleDateFormat类来实现。 SimpleDateFormat类是DateFormat的一个具体子类,它可以用于格式化日期(即将日期转换为指定格式的字符串)和解析日期(即将字符串解析为日期对象)。 要进行日期格式转换,首先需要创建一个SimpleDateFormat对象,并指定要转换的日期格式。例如,可以使用"yyyy-MM-dd"表示年-月-日的格式,"HH:mm:ss"表示:分:秒的格式。 比如,要将日期对象转换为指定格式的字符串,可以使用SimpleDateFormat的format()方法。例如: ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String strDate = sdf.format(new Date()); ``` 这样就会将当前日期转换为"yyyy-MM-dd"格式的字符串。 另外,要将字符串解析为日期对象,可以使用SimpleDateFormat的parse()方法。例如: ``` SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse("2022-12-31"); ``` 这样就会将字符串"2022-12-31"解析为对应的日期对象。 需要注意的是,日期格式中的字母必须与日期字符串的格式一一对应,否则会抛出解析异常。所以,在进行日期格式转换,要确保指定的格式与实际的日期字符串格式相匹配。 除了提供预定义的日期格式外,SimpleDateFormat还支持自定义日期格式,可以通过在日期格式字符串中添加特定的字符来表示各个日期部分的格式。 综上所述,通过Java的SimpleDateFormat类,可以方便地进行日期格式的转换,实现日期对象与字符串之间的相互转换。 ### 回答3: Java日期格式转换可以通过Java中提供的DateFormat类来实现。 DateFormat类是一个抽象类,它可以将日期和时间按照指定的格式进行格式化输出,也可以将格式化后的日期和时间字符串解析为Date对象。 日期格式转换的一般流程如下: 1. 创建DateFormat对象,指定日期格式的模式。 SimpleDateFormat类是DateFormat的一个实现类,通过它可以指定具体的日期格式模式。 2. 调用DateFormat的format()方法进行日期格式化,将Date对象转换为指定格式的日期字符串。 该方法需要传入一个Date对象作为参数,并返回一个格式化后的日期字符串。 3. 调用DateFormat的parse()方法进行日期解析,将格式化后的日期字符串转换为Date对象。 该方法需要传入一个格式化后的日期字符串作为参数,并返回一个解析后的Date对象。 以下是一个简单的示例代码,将日期转换为指定格式的字符串,并将字符串解析为日期对象: ```java import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class DateConversionExample { public static void main(String[] args) { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date currentDate = new Date(); // 将日期转换为指定格式的字符串 String formattedDate = dateFormat.format(currentDate); System.out.println("格式化后的日期:" + formattedDate); try { // 将格式化后的日期字符串解析为日期对象 Date parsedDate = dateFormat.parse(formattedDate); System.out.println("解析后的日期:" + parsedDate); } catch (Exception e) { System.out.println("日期解析错误:" + e.getMessage()); } } } ``` 以上代码中,DateFormat对象使用了"yyyy-MM-dd HH:mm:ss"模式进行日期格式化和解析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值