Java:将表示两位年份的字符串转换为四位数字

6

这个问题已经被多次提出,但我有一个问题觉得这是一个独特的问题。

问题如下:

我有一个字符串,表示两位数的年份。例如在输入2016时,我输入16。

我需要将两位数的年份转换为四位数的年份,即将16变成2016。

通过查阅一些问题和答案,我得出了以下结论:

解决方案1

DateFormat sdfp = new SimpleDateFormat("dd.mm.yy");
Date d = sdfp.parse(input);
DateFormat sdff = new SimpleDateFormat("yyyy-MM-dd");
String date = sdff.format(d);

虽然很好,但在我的情况下只有年份,没有月份或日期,我找不到一种方法来只使用年份创建日期对象。

解决方案2

可以用 Calendar 对象解决上述问题,但它不允许输入两位数的年份。

编辑 忘记提到我不能使用Joda-Time,因为我正在使用Android平台,这会增加我项目的大小,而仅仅是为了这样一个小需求。


如果需要使用日期对象,我相信有一个特定的短日期格式仅包含年份。如果没有,您可以默认使用任何日期,然后始终将其显示为仅包含年份的短字符串。 - James
6个回答

11

为什么不直接从格式中去掉月份和日期这部分呢?

DateFormat sdfp = new SimpleDateFormat("yy");
Date d = sdfp.parse(input);
DateFormat sdff = new SimpleDateFormat("yyyy");
String date = sdff.format(d);

LIVE

这里是有关于SimpleDateFormat如何解释缩写年份的规则。(加粗为本人添加)

对于使用缩写年份模式(“y”或“yy”)进行解析,SimpleDateFormat必须将缩写年份与某个世纪相关联。它通过调整日期来使其在SimpleDateFormat实例创建时间之前80年和之后20年内。(译注:指相对于当前时间而言)。例如,使用模式“MM/dd/yy”和在1997年1月1日创建的SimpleDateFormat实例,则字符串“01/11/12”将被解释为2012年1月11日,而字符串“05/04/64”将被解释为1964年5月4日。


1
事实证明,OP计划在未来一百多年内使用这段代码,我认为这个解决方案不是“可扩展的”。它可以在短时间内工作,但当它需要处理旧数据(-20年),这对于一个将工作80多年的应用程序是有意义的时候,它将不能按预期工作。 - Gavriel
这意味着如果输入字符串为37,则它会给我们2036年,然后跳到1937年。那么如果输入是“100”呢? - Scitech
@Scitech,不,这还算是一个比较好的情况,因为你知道可以期待什么。但根据黄色段落所述,这取决于SimpleDateFormat对象何时被创建... 所以你并不真正知道任何东西。 - Gavriel
@Gavriel对!有没有SimpleDateFormat的替代方案? - Scitech
@Gavriel Android大概80年后甚至都不会存在。 - nasch

4
我认为这个简单多了:
String year = "20" + input;

但是,如果您希望使用户的生活更轻松,并假设他输入的是有效的卡片号码,那么这个问题就很容易解决:如果他输入了两位数字,则添加(thisYear/100) 。如果此时间似乎在过去,则如果它比90年以上,则再添加100(这只会发生在任何世纪的最后十年)。

Date now = new Date();
int expYear = (int)(now.getYear()/100) + parseInt(input);
if (expYear < now.getYear() && expYear+90<now.getYear()) {
    expYear += 100;
}

1
是的,这是解决方案,但应用程序会在2100年崩溃 :D - Ersen Osman
1
这就是为什么现在没有理智的程序员会接受两位数的年份。 - Tom
3
如果你打算让你的应用程序在2100年之后继续工作,请不要使用两位数字来表示年份!!! - Gavriel
@Gavriel 哈哈,到那时候我就变成罐中之脑了 :) - Ersen Osman
1
我认为这是一个足够的解决方案,因为它是针对Android应用程序的。到2100年,现在编写的任何Android应用程序都不会再被使用。要么Android已经进化了,应用程序已经更新(如果不是功能,则为设计),或者被新技术替代。 - Kevin
显示剩余4条评论

2
  public static int adjustOneOrTwoDigitYearInput(int year) {
    return adjustOneOrTwoDigitYearInput(year, Year.now().getValue());
  }

  public static int adjustOneOrTwoDigitYearInput(int inputYear, int referenceYear) {
    if(inputYear > 99) {
      return inputYear;
    }

    int currentCentury = referenceYear / 100 * 100;
    int currentCenturyYear = currentCentury + inputYear;
    int upperLimit = referenceYear + 20;
    int lowerLimit = referenceYear - 79;

    // initially place it in current century
    int adjusted = currentCenturyYear;

    if(adjusted> upperLimit) {
      // shift a century down
      adjusted -= 100;
    }
    else if(adjusted < lowerLimit) {
      // shift a century up
      adjusted += 100;
    }

    return adjusted;
  }

一些测试:

  @Test
  public void test_adjustOneOrTwoDigitYearInput()
  {
    assertEquals(2017, adjustOneOrTwoDigitYearInput(17, 2017));
    assertEquals(2037, adjustOneOrTwoDigitYearInput(37, 2017)); // +20
    assertEquals(1938, adjustOneOrTwoDigitYearInput(38, 2017)); // +21
    assertEquals(2000, adjustOneOrTwoDigitYearInput(0, 2017)); // 0
    assertEquals(1999, adjustOneOrTwoDigitYearInput(99, 2017)); // 99

    assertEquals(2078, adjustOneOrTwoDigitYearInput(78, 2078)); 
    assertEquals(2098, adjustOneOrTwoDigitYearInput(98, 2078)); // + 20
    assertEquals(1999, adjustOneOrTwoDigitYearInput(99, 2078)); // + 21 / 99
    assertEquals(2000, adjustOneOrTwoDigitYearInput(0, 2078)); // 0

    assertEquals(1990, adjustOneOrTwoDigitYearInput(90, 1990));
    assertEquals(1999, adjustOneOrTwoDigitYearInput(99, 1990)); // 99
    assertEquals(2000, adjustOneOrTwoDigitYearInput(0, 1990)); // 0
    assertEquals(2010, adjustOneOrTwoDigitYearInput(10, 1990)); // +20
    assertEquals(1911, adjustOneOrTwoDigitYearInput(11, 1990)); // +21
  }

1
如果你使用Java 8,可以使用java.time中的Year:
Year year = Year.parse("18", DateTimeFormatter.ofPattern("yy"));
year.toString(); //This returns 2018

0

您也可以尝试类似这样的代码:

String input = "16";
String str = String.valueOf(Calendar.getInstance().get(Calendar.YEAR)).substring(0, 2)+input;
System.out.println("str = " + str);

结果如下:

str = 2016

0
一个相当简单的问题。由Gavriel提供。
 String year = "20" + input;
if(input>99)
{
String year= "2"+input;
}

糟糕了!输入数字16可能会与2016年和2116年混淆,这是一个世纪问题。 - Scitech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接