繁体   English   中英

具有未知日、月和/或年的 Java 日期实现

[英]Java Date implementation with unknown day, month and/or year

有些真人不知道自己是哪一天、哪一月甚至哪一年出生的。

这可能会给需要完整出生日期的系统带来问题。

在荷兰,决定用未知数对这些生日进行编码。 以下是 1975 年出生的人的生日,确切日期不详:

00-00-1975

我如何在 Java 中处理这个问题? 我不是在问解析字符串“00-00-1975”,而是一个支持未知(可能为空?)值的实际日期实现。

值得庆幸的是,决策者在 2014 年明智了,现在出生日期不详的人得到了一个确定的日期。 https://www.binnenlandsbestuur.nl/bestuur-en-organisatie/nieuws/niet-bestaan​​de-geboortedatum-00-00-jj-blijft.9484714.lynkx

不,没有这种事。 您可以实现自己的,例如

interface Birthday {
    Optional<LocalDate> fullDate();
    Year year();
}

class UnknownBirthday implements Birthday {
    private final Year year;
    // ctor

    @Override
    public Year year() {
        return year;
    }

    @Override
    public Optional<LocalDate> fullDate() {
        return Optional.empty();
    }
}

class KnownBirthday implements Birthday {
    private final LocalDate date;
    // ctor
    
    @Override
    public Optional<LocalDate> fullDate() {
        return Optional.of(date);
    }

    @Override
    public Year year() {
        return Year.of(date.getYear());
    }
}

一种选择是利用TemporalAccessor接口。 几乎所有 java.time 的日期和时间类都实现了这个接口,当然还有那些您将在不确定的生日时使用的类。 将变量声明为TemporalAccessor ,您可以为其分配YearLocalDate或其他类型。

一些程序员会很想对这样的变量使用instanceof很多,这可能被认为不太好。 幸运的是,出于许多目的,它也不是必需的。 TemporalAccessorisSupported方法可以在大多数情况下使用。

演示:

    // Example birthdays ordered from the best known to the completely unknown
    TemporalAccessor[] birthdays = {
            LocalDate.of(1955, Month.MARCH, 22),
            YearMonth.of(1978, Month.MAY),
            Year.of(1969),
            IsoEra.CE
    };

    for (TemporalAccessor birthday : birthdays) {
        String yearString = birthday.isSupported(ChronoField.YEAR)
                ? String.valueOf(birthday.get(ChronoField.YEAR))
                : "N/A";
        String monthString = birthday.isSupported(ChronoField.MONTH_OF_YEAR)
                ? Month.from(birthday).toString()
                : "N/A";
        String dateString = birthday.isSupported(ChronoField.DAY_OF_MONTH)
                ? String.valueOf(birthday.get(ChronoField.DAY_OF_MONTH))
                : "N/A";

        System.out.format("%-10s %4s %-9s %3s%n", birthday, yearString, monthString, dateString);
    }

这个片段的输出是:

 1955-03-22 1955 MARCH 22 1978-05 1978 MAY N/A 1969 1969 N/AN/A CE N/AN/AN/A

为了获得更好的界面,您可以将TemporalAccessor包装在一个自制的类中。 例如,您的类可能有YearLocalDate getter,在没有足够数据的情况下,它们可能会返回空的Optionalnull 你可以想到更多方便的方法。 你最了解你的要求,所以我把设计的细节留给你自己。

Joda Time 库具有Partial类,可用于创建未知月/日等的日期。

Partial 是一个不可变的部分日期时间,支持任何一组日期时间字段。

Partial 实例可用于保存字段的任意组合。 该实例不包含时区,因此任何日期时间都是本地的。

    Partial date = new Partial();
    
    // prints 1975
    System.out.println( date.with(year(), 1975) );

    // prints 1975-03
    System.out.println( date.with(monthOfYear(), 3).with(year(), 1975));

    // prints 1975-03-28
    System.out.println( date.with(dayOfMonth(), 28).with(monthOfYear(), 3).with(year(), 1975));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM