java 如何格式化只有一个偏移量,但支持多个偏移量与DateTimeFormatterBuilder与从joda迁移?

au9on6nz  于 2023-02-14  发布在  Java
关注(0)|答案(2)|浏览(146)

我想将代码从Joda迁移到java. time。我使用DateTimeFormatter解析和格式化多个日期。问题在于DateTimeFormatter.format(...),返回的字符串是“2023-02- 08 T09:30:00.000+01:00+0100+01”,而不是2023-02- 08 T09:30:00.000+01:00
我写了一个测试来暴露我的问题。错误的测试是testFormatWithJava()

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAccessor;
import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.Before;
import org.junit.Test;

public class TestU {

    private DateTimeFormatter dateTimeFormatter;

    @Before
    public void before() {
        DateTimeFormatterBuilder dateTimeFormatterBuilder = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME) //
                .optionalStart().appendPattern(".SSS").optionalEnd() //
                .optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd() //
                .optionalStart().appendOffset("+HHMM", "+0000").optionalEnd() //
                .optionalStart().appendOffset("+HH", "Z").optionalEnd();
        dateTimeFormatter = dateTimeFormatterBuilder.toFormatter();
    }

    @Test
    public void testParseDateStringWithJoda() {
        String dateString1 = "2023-02-08T09:30:00.787+0000";
        String dateString2 = "2023-02-08t09:30:00.000+01:00";
        String dateString3 = "2013-07-05t14:04:15+01:00";

        org.joda.time.format.DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withOffsetParsed();
        org.joda.time.format.DateTimeFormatter formatterWithoutMs = ISODateTimeFormat.dateTimeNoMillis()
                .withOffsetParsed();

        DateTime dateTime1 = formatter.parseDateTime(dateString1);
        DateTime dateTime2 = formatter.parseDateTime(dateString2);
        DateTime dateTime3 = formatterWithoutMs.parseDateTime(dateString3);

        assertEquals("Wed Feb 08 10:30:00 CET 2023", dateTime1.toDate().toString());
        assertEquals("Wed Feb 08 09:30:00 CET 2023", dateTime2.toDate().toString());
        assertEquals("Fri Jul 05 15:04:15 CEST 2013", dateTime3.toDate().toString());
    }

    @Test
    public void testParseDateStringWithJava() {
        String dateString1 = "2023-02-08T09:30:00.787+0000";
        String dateString2 = "2023-02-08t09:30:00.000+01:00";
        String dateString3 = "2013-07-05t14:04:15+01:00";

        TemporalAccessor temporalAccessor1 = dateTimeFormatter.parse(dateString1);
        TemporalAccessor temporalAccessor2 = dateTimeFormatter.parse(dateString2);
        TemporalAccessor temporalAccessor3 = dateTimeFormatter.parse(dateString3);

        assertEquals("Wed Feb 08 10:30:00 CET 2023", Date.from(Instant.from(temporalAccessor1)).toString());
        assertEquals("Wed Feb 08 09:30:00 CET 2023", Date.from(Instant.from(temporalAccessor2)).toString());
        assertEquals("Fri Jul 05 15:04:15 CEST 2013", Date.from(Instant.from(temporalAccessor3)).toString());
    }

    @Test
    public void testFormatWithJoda() {
        Date date = Date.from(LocalDateTime.of(2023, 02, 8, 9, 30).atZone(ZoneId.of("Europe/Paris")).toInstant());

        org.joda.time.format.DateTimeFormatter formatter = ISODateTimeFormat.dateTime().withOffsetParsed();
        DateTime dt = new DateTime(date);

        assertEquals("2023-02-08T09:30:00.000+01:00", formatter.print(dt));
    }

    @Test
    public void testFormatWithJava() {
        Date date = Date.from(LocalDateTime.of(2023, 02, 8, 9, 30).atZone(ZoneId.of("Europe/Paris")).toInstant());

        assertEquals("2023-02-08T09:30:00.000+01:00",
                dateTimeFormatter.withZone(ZoneId.systemDefault()).format(date.toInstant()));
    }
}
k0pti3hp

k0pti3hp1#

您希望能够解析4种可能的格式,而不是4个连接的可选结尾。
应使用DateTimeFormatterBuilder #appendOptional将所需的4个变量添加到DateTimeFormatterBuilder中。
大概是这样的

dateTimeFormatter = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .appendOptional(DateTimeFormatter.ofPattern("with .SSS"))
    .appendOptional(DateTimeFormatter.ofPattern("with +HH:MM"))
    .appendOptional(DateTimeFormatter.ofPattern("with +HHMM"))
    .appendOptional(DateTimeFormatter.ofPattern("with +HHZ"))
    .toFormatter();
sd2nnvve

sd2nnvve2#

可选部分适用于将字符串解析为DateTime示例,但不适用于格式化。格式化时,您应该创建一个或多个DateTimeFormatter,不包含任何可选部分,这些可选部分将反映您的日期格式设置标准。可选部分适用于解析字符串,其中字符串可能具有多种格式,并且您无法对其进行任何控制。我曾经写过一个特性,我尝试解析任何已知格式的字符串,所以我有一个属性文件,其中有几种格式,一个接一个,应该涵盖所有的可能性,我尝试解析传入的字符串,每一种格式,一个接一个,直到第一次成功,或直到我用完格式。把它放在文件中允许我添加和重新排列格式而不需要改变代码。我写了一篇关于它的文章,详细描述了这个想法。下面是文章:Java 8 java.time package: parsing any string to date

相关问题