【问题标题】:Parsing dates with no years that span across 12 months of data解析跨越 12 个月数据的没有年份的日期
【发布时间】:2016-03-16 17:55:21
【问题描述】:

我有一些日期以MM/dd 格式指定的项目,但没有指定年份。

但是,数据的上下文中隐含了年份,因为数据显示的日期不超过“当前日期”(在数据中指定)12 个月内

例如,假设当前日期是 2013 年 1 月 31 日。 这意味着从 2012 年 2 月 1 日到 2013 年 1 月 31 日(含)会有信息。

我在这里面临的问题是,因为数据中没有指定年份,所以我需要自己生成年份,然后才能将它们加载到我的数据库中。

从数据的上下文中,我们知道任何大于当前月份的日期都来自上一年,而任何小于或等于当前月份的日期都是当前年份。

所以假设当前日期是 2013 年 1 月,我们有类似

01/31 - 2013
01/01 - 2013
12/31 - 2012
02/29 - 2012

现在,这里的问题是最后一行的日期。

2012 年是闰年,所以 2 月 29 日确实存在。 但是,2013 年不是。

我目前的日期解析方法如下(使用SimpleDateFormat

  1. 获取日期:01/31
  2. 将当前年份附加到它:01/31/2016
  3. 使用日期格式MM/dd/yyyy解析日期

日期解析是在严格模式下执行的,所以像 02/29 这样的日期不会滚动到 03/01。

但是,这个算法在闰年会失败,因为假设当前年份是 2013 年,我将尝试解析 02/29/2013,它会失败。

我可以使用什么方法来确定日期的年份?

【问题讨论】:

  • 您的要求不明确。您将 1/31 显示为 2013 年,但 2012 年 1 月 31 日距当前日期 2012 年 1 月 1 日不到 12 个月。
  • @JimmyJames 为了清楚起见,我加了几天。

标签: java date


【解决方案1】:

将日/月解析为java.time.MonthDay,将其与MonthDay.now() 进行比较,然后根据结果调用atYear 并使用正确的年份(例如使用Year.now())。

您可能还想考虑time zones

假设输入格式正确并忽略时区问题,应用于您的示例的简单版本可能如下所示:

public static void main(String[] args) {
  m("01/31", YearMonth.of(2013, 1));
  m("01/01", YearMonth.of(2013, 1));
  m("12/31", YearMonth.of(2013, 1));
  m("02/29", YearMonth.of(2013, 1));
}

private static void m(String date, YearMonth currentMonth) {
  DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd");
  MonthDay md = MonthDay.parse(date, fmt);
  int year = currentMonth.getYear();
  MonthDay cutoffDate = MonthDay.from(currentMonth.atEndOfMonth());
  if (md.isAfter(cutoffDate)) year--;
  LocalDate result = md.atYear(year);
  System.out.println(date + " - " + year + " ==> " + result);
}

哪个输出:

01/31 - 2013 ==> 2013-01-31
01/01 - 2013 ==> 2013-01-01
12/31 - 2012 ==> 2012-12-31
02/29 - 2012 ==> 2012-02-29

【讨论】:

  • 这似乎是 Java 8 中的一个新类。我不知道这个!
  • 你能提供一个如何将01/31 解析为 MonthDay 的示例吗?我只尝试了MonthDay.parse("01/31"),但它的格式不正确。
  • @MxyL 用于解析,默认情况下,预期格式为--MM-dd,如--12-03,采用ISO 8601 标准的样式。对于其他格式,定义一个DateTimeFormatter
  • 另外,请记住 java.time 现在已内置到 Java 中。因此,您应该在整个代码库中传递 MonthDay 类型的对象,而不是重复解析/生成字符串。使用这种特定类型可以为您提供类型安全、有效值和自记录代码。
【解决方案2】:

你不能按照你想要的方式去做。在将整个内容放入Date 之前,您必须从月份和日期确定年份。下面是一些伪代码,假设日期总是在前一年内,并且等于今天的日期是今天而不是 1 年前(根据需要进行调整):

int cy = current year
int cm = current month
int cd = current day of month
int im = input month
int id = input day of month
int year = (im < cm || im==cm && id <= cd) ? cy : cy-1
try 
    Date d = new Date(year, im, id) strict
catch 
    invalid date

【讨论】:

  • 这是有道理的。我基本上会手动解析日期,而不是依靠日期库来为我做。幸运的是,我不必考虑夏令时或其他常见的时间相关情况,所以还不错。
【解决方案3】:

那么如何做类似的事情:

  1. 从您的文件中获取日期。
  2. 追加当前年份。
  3. 获取今天的日期。
  4. 比较今天的日期和文件的日期。如果今天的日期早于,则从文件日期中减去一年。
  5. 解析文件日期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    相关资源
    最近更新 更多