【问题标题】:Java Date implementation with unknown day, month and/or year日期、月份和/或年份未知的 Java 日期实现
【发布时间】:2021-12-26 21:13:38
【问题描述】:

有些真实的人不知道他们出生的日期、月份甚至年份。

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

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

00-00-1975

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

谢天谢地,决策者在 2014 年变得明智,现在出生日期不详的人得到了一个虚构的日期。 https://www.binnenlandsbestuur.nl/bestuur-en-organisatie/nieuws/niet-bestaande-geboortedatum-00-00-jj-blijft.9484714.lynkx

【问题讨论】:

  • 该死的好问题!
  • @Zorglube 这确实是一个有趣的问题......不幸的是不适合 SO。在这里询问图书馆之类的东西是题外话。
  • @Michael 您在哪里看到“这东西在标准库中吗?”这个问题?
  • 我猜你必须建立自己的库来处理这个问题。
  • 投票重新开放。这是一个很好的问题,有一个很好的答案。 @Ivana 编辑您的问题以避免要求实施。只需询问“如何处理”即可避免这种下意识的近距离投票。

标签: java date validation


【解决方案1】:

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

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());
    }
}

【讨论】:

  • 很好的解决方案。可以使用 YearMonth 类进一步扩展,以应对年份和月份已知但月份日期未知的情况。
【解决方案2】:

一种选择是利用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);
    }

这个 sn-p 的输出是:

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

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

【讨论】:

    【解决方案3】:

    Joda Time libraryPartial 类,可用于创建未知月份/日期等的日期。

    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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      相关资源
      最近更新 更多