如何用t和z将localdate格式化为iso8601?

jtw3ybtb  于 2021-06-26  发布在  Java
关注(0)|答案(3)|浏览(651)

我试图生成一个随机的日期和时间,并将其转换为 "yyyy-MM-dd'T'HH:mm:ss'Z'" 格式。
以下是我尝试过的:

public static String generateRandomDateAndTimeInString() {
    LocalDate date = LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
    System.out.println("date and time :: " + date.toString());
    return formatDate(date) ;
  }

  public static String formatDate(LocalDate date){
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    return dateFormat.format(date);
  }

但是排队的时候 dateFormat.format(date) ,投诉:
java.lang.illegalargumentexception:无法将给定对象格式化为日期
第二个问题是,打印输出不包含时间:

date :: 1998-12-24

我不知道怎么让它工作。

u91tlkcl

u91tlkcl1#

ZoneOffset utc = ZoneOffset.UTC;
    LocalDate today = LocalDate.now(utc);
    LocalDate seventyYearsAgo = today.minusYears(70);
    int totalDays = Math.toIntExact(ChronoUnit.DAYS.between(seventyYearsAgo, today));
    LocalDate date = today.minusDays(new Random().nextInt(totalDays));
    String dateString = date.atStartOfDay(utc).toString();
    System.out.println("date and time :: " + dateString);

输出示例:
日期和时间:1983-08-24t00:00z
注意事项:
让java.time从年转换为天。它提供了更可读和更正确的代码(一年并不总是365天)。
若要在字符串中包含时间和utc偏移量,请将 ZonedDateTime 或者一个 OffsetDateTime 因为这样的物体持有一天中的时间和偏移量。一 LocalDate 没有。这是一个没有时间的日期,也没有utc的偏移量。这个 Z 您要求的值表示与utc的偏移量为0。
如果你想在输出中也包含小时、分钟和秒,你可以通过计算秒而不是天来实现。在这种情况下使用 OffsetDateTime 整个操作(或 ZonedDateTime 如果在与utc不同的时区)。

ZoneOffset utc = ZoneOffset.UTC;
    OffsetDateTime today = OffsetDateTime.now(utc).truncatedTo(ChronoUnit.SECONDS);
    OffsetDateTime seventyYearsAgo = today.minusYears(70);
    long totalSeconds = ChronoUnit.SECONDS.between(seventyYearsAgo, today);
    OffsetDateTime date = today.minusSeconds(ThreadLocalRandom.current().nextLong(0, totalSeconds));
    String dateString = date.toString();
    System.out.println("date and time :: " + dateString);

日期和时间:1996-09-21t06:49:56z
我正在使用 ThreadLocalRandom 因为它可以在指定的时间间隔内生成一个随机的长值。有趣的 ThreadLocalRandom 有很多方便的方法 Random 还没有。

0aydgbwb

0aydgbwb2#

如果您想忽略时间部分,那么可以使用 ZonedDateTime 这样地:

DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
return ZonedDateTime.of(
        date, 
        LocalTime.MIN, 
        ZoneId.of("Europe/Paris")
).format(dateFormat);

输出示例

2013-10-19T00:00:00+0200

或者更好,你可以用 toString 以字符串形式获取格式化日期,默认格式为 ZonedDateTime :

return ZonedDateTime.of(
        date,
        LocalTime.MIN,
        ZoneId.of("Europe/Paris")
).toString();

输出

2013-10-19T00:00+02:00[Europe/Paris]

笔记
这个日期总是和你在一起 00:00:00 作为时间的一部分,因为我们正在使用 LocalTime.MIN 此外,您还可以更改 ZoneId 达到预期效果 Zone ,这只是一个例子。
重要的 DateFormat 以及 SimpleDateFormat 是传统的图书馆,所以请不要把它们和 java.time 图书馆,在你用的最上面 LocalDate 也就是说你在用这个 java.time 所以在你所有的代码中继续使用它。

fhity93d

fhity93d3#

不要使用simpleDataFormat格式化java.time类型

使用 SimpleDateFormat ,您应该只格式化旧的日期时间类型,例如。 java.util.Date . 为了格式化 java.time 日期时间类型,您需要使用 DateTimeFormatter .

切勿将z括在单引号内

封闭是个错误 Z 在格式的单引号内。符号 Z 代表 zulu 并指定 UTC+00:00 . 如果你把它括在单引号里,它只意味着字符文字, Z 不会起到 UTC+00:00 正在解析。

您不需要显式地使用格式化程序

对于这个需求,您不需要显式地使用格式化程序,因为 OffsetDateTime#toString 已经以您需要的格式返回字符串。但是,如果 OffsetDateTime 对象为零,则相同且后续较小的单位被截断 OffsetDateTime#toString . 如果您需要完整的格式而不考虑秒的值,那么,当然,您必须使用 DateTimeFormatter .

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        System.out.println(generateRandomDateAndTimeInString());
    }

    public static String generateRandomDateAndTimeInString() {
        LocalDate date = LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
        System.out.println("date and time :: " + date.toString());
        return formatDate(date);
    }

    public static String formatDate(LocalDate date) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
        // return date.atStartOfDay().atOffset(ZoneOffset.UTC).toString();
        return date.atStartOfDay().atOffset(ZoneOffset.UTC).format(dtf);
    }
}

示例运行:

date and time :: 1996-09-05
1996-09-05T00:00:00Z

注意,api的日期时间 java.util 以及它们的格式化api, SimpleDateFormat 过时且容易出错。建议完全停止使用它们,并切换到现代日期时间api。
出于任何原因,如果您必须坚持使用Java6或Java7,您可以使用threeten backport,它将大部分java.time功能向后移植到Java6和Java7。
如果您正在为一个android项目工作,并且您的android api级别仍然不符合java-8,请检查通过desugaring提供的java8+api以及如何在android项目中使用threetenabp。
从trail:date-time了解有关现代日期时间api的更多信息。

如果出于任何原因仍需要使用SimpleDataFormat:

转换 LocalDateZonedDateTimeZoneOffset.UTC 在一天的开始➡️ 转换 ZonedDateTimeInstant ➡️ 获得 java.util.Date 对象来自 Instant .

public static String formatDate(LocalDate date) {
    Date utilDate = Date.from(date.atStartOfDay(ZoneOffset.UTC).toInstant());
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
    return dateFormat.format(utilDate);
}

相关问题