Java8日期格式化

Java8之前的版本,格式化日期常使用SimpleDateFormat,但这个类并不是线程安全的,通常要用作局部变量或者使用ThreadLocal包装。或者使用额外的joda time 依赖来对日期进行操作。

但是到了Java8,这类烦恼都没有了,全新的日期api可以快速实现日期格式化。

1.日期格式化-字符串转换成日期

    /**
     * 将不带时间的日期字符串转为日期
     *
     * @param dateStr 字符串
     * @param format  该字符串对应的日期格式,必须一一对应,否则返回null
     * @return 日期对象,当格式不匹配会返回null
     */
    public static Date toDate(String dateStr, String format) {
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(format);
        try {
            LocalDate localDate = LocalDate.parse(dateStr, inputFormatter);
            ZoneId defaultZoneId = ZoneId.systemDefault();
            return Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 将带时间的格式转换为日期
     * @param dateStr 字符串
     * @param format 该字符串对应的日期时间格式,必须一一对应,否则返回null
     * @return 日期对象,当格式不匹配会返回null
     */
    public static Date toDateTime(String dateStr, String format) {
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(format);
        try {
            LocalDateTime localDateTime = LocalDateTime.parse(dateStr, inputFormatter);
            ZoneId defaultZoneId = ZoneId.systemDefault();
            ZonedDateTime zdt = localDateTime.atZone(defaultZoneId);
            return Date.from(zdt.toInstant());
        } catch (Exception e) {
            return null;
        }
    }

测试代码及输出:

        String str4 = "2022-08-16";
        System.out.println(toDate(str4, "yyyy-MM-dd"));
        String str5 = "2022-08-16 12:05:24";
        System.out.println(toDateTime(str5, "yyyy-MM-dd HH:mm:ss"));
Tue Aug 16 00:00:00 CST 2022
Tue Aug 16 12:05:24 CST 2022

2.日期字符串转换

  /**
   * 不带时分秒的日期字符串转化
   *
   * @param input 输入的日期
   * @param inputFormat 输入日期的格式
   * @param outputFormat 输出日期的格式
   * @return 输出的日期,不带时分秒
   */
  public static String formattedDate(String input, String inputFormat, String outputFormat) {
    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputFormat);
    LocalDate localDate = LocalDate.parse(input, inputFormatter);

    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputFormat);
    return localDate.format(outputFormatter);
  }

测试代码及输出:

    String output1 = formattedDate("2019年07月15日", "yyyy年MM月dd日", "yyyy-MM-dd");
    String output2 = formattedDate("2019/07/16", "yyyy/MM/dd", "yyyy-MM-dd");
    String output3 = formattedDate("2019-07-16", "yyyy-MM-dd", "yyyy/MM/dd");

    System.out.println(output1);
    System.out.println(output2);
    System.out.println(output3);
2019-07-15
2019-07-16
2019/07/16

注意,使用LocalDate + DateTimeFormatter仅仅能够转换不带时分秒的日期格式!

3.带时间日期字符串转换

  /**
   * 带时分秒的日期字符串转换
   *
   * @param input 输入的日期
   * @param inputFormat 输入日期的格式
   * @param outputFormat 输出日期的格式
   * @return 输出指定格式的日期,可以带时分秒,也可以不带
   */
  public static String formattedDateTime(String input, String inputFormat, String outputFormat) {
    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputFormat);
    LocalDateTime localDateTime = LocalDateTime.parse(input, inputFormatter);

    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputFormat);
    return localDateTime.format(outputFormatter);
  }

测试代码及输出:

    String output1 = formattedDateTime("20190713000000", "yyyyMMddHHmmss", "yyyy-MM-dd");
    String output2 = formattedDateTime("20190713000000", "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss");

    String output3 = formattedDateTime("2019年07月14日00时00分00秒", "yyyy年MM月dd日HH时mm分ss秒",
        "yyyy/MM/dd");
    String output4 = formattedDateTime("2019年07月14日00时00分00秒", "yyyy年MM月dd日HH时mm分ss秒",
        "yyyyMMddHHmmss");

    String output5 = formattedDateTime("2019-07-15 00:00:00", "yyyy-MM-dd HH:mm:ss", "yyyyMMdd");
    String output6 = formattedDateTime("2019-07-15 00:00:00", "yyyy-MM-dd HH:mm:ss",
        "yyyy年MM月dd日HH时mm分ss");

    System.out.println(output1);
    System.out.println(output2);
    System.out.println(output3);
    System.out.println(output4);
    System.out.println(output5);
    System.out.println(output6);
2019-07-13
2019-07-13 00:00:00
2019/07/14
20190714000000
20190715
2019年07月15日00时00分00

注意:使用LocalDateTime +  DateTimeFormatter 可以将指定日期类型转换成任意形式的日期类型。

4.Date和LocalDateTime互转

  /**
   * LocalDateTime -> Date
   */
  public static Date toDate(LocalDateTime localDateTime) {
    ZoneId zoneId = ZoneId.systemDefault();
    ZonedDateTime zdt = localDateTime.atZone(zoneId);
    return Date.from(zdt.toInstant());
  }

  /**
   * Date -> LocalDateTime
   */
  public static LocalDateTime toLocalDateTime(Date date) {
    Instant instant = date.toInstant();
    ZoneId zoneId = ZoneId.systemDefault();
    return instant.atZone(zoneId).toLocalDateTime();
  }

5.Date和LocalDate互转

    /**
     * Date -> LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * LocalDate -> Date
     */
    public static Date toDate(LocalDate localDate) {
        ZoneId defaultZoneId = ZoneId.systemDefault();
        return Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
    }

6.为什么推荐使用DateTimeFormatter而不是SimpleDateFormat

不仅仅安全,而且更加严格。

举例:当日期格式为 yyyy-MM-dd,输入日期为2022-8-16,对于SimpleDateFormat即使设置强校验模式,依然能够转换成功,但是对于DateTimeFormatter则会转换失败

        String str = "2022-8-16";
        System.out.println(toDate(str, "yyyy-MM-dd"));
        String str2 = "2022-8-16";
        System.out.println(toDateUseSdf(str2, "yyyy-MM-dd"));
    public static Date toDateUseSdf(String dateStr, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setLenient(true);
        try {
            return sdf.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }

分别输出null和 Tue Aug 16 00:00:00 CST 2022

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alphathur

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值