在 java 中将 "mm/yy" 转换为 "yyyy-mm-dd"

Convert "mm/yy" to "yyyy-mm-dd" in java

我需要将 "11/17" 字符串日期(2017 年 11 月)转换为 "2017-11-01"(2017 年 11 月 1 日)。

在 Java 中实现此目标的最佳方法是什么?

我试过了:

String dayMonthYear = "11/17";
dayMonthYear = "01/" + dayMonthYear;

DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yy");
DateTime dt = formatter.parseDateTime(dayMonthYear);
dt.year().setCopy(dt.getYear() + 2000);

DateTimeFormatter dtfOut = DateTimeFormat.forPattern("yyyy-MM-dd");
dayMonthYear = dtfOut.print(dt);
System.out.println(dayMonthYear); // "2017-11-01";

并且:

SimpleDateFormat dateFormatTwoDigitsYear = new SimpleDateFormat(TWO_DIGITS_YEAR_DATE_FORMAT);  //"dd/MM/yy"
SimpleDateFormat dateFormatFourDigitsYear = new SimpleDateFormat(FOUR_DIGITS_YEAR_DATE_FORMAT);//  "yyyy-MM-dd"
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, -100);//??? I AM NOT SURE WHY DO I NEEED THIS??
dateFormatTwoDigitsYear.set2DigitYearStart(calendar.getTime());
try
{
    dayMonthYear = dateFormatFourDigitsYear.format(dateFormatTwoDigitsYear.parse(dayMonthYear));
}
catch (ParseException e)
{
    log.error("Error while formatting date in yyyy-MM-dd format. Date is " + dayMonthYear);
}

我不确定为什么在第二种方法中需要这一行:

calendar.add(Calendar.YEAR, -100);

他们都在工作。但是不知道有没有更好的解决办法

您可以定义两种实用方法,一种将字符串转换为日期,另一种将其转换回字符串。

static Date stringToDate(String string) throws ParseException
{
    DateFormat dateFormat = new SimpleDateFormat("MM/yyyy");
    return dateFormat.parse(string);
}

static String dateToString(Date date)
{
    DateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd");
    return outputFormatter.format(date);
}

static String formatString(String string)
{
    return dateToString(stringToDate(string));
}


//Just call formatString() with your argument

如果您只想将第一种字符串类型转换为第二种类型,则可以组合它们,但我喜欢将它们分开,以防我需要来自字符串的日期对象或直接来自日期对象的字符串。

您不需要为年份添加值。 2 位数的值 (17) 会自动调整为 2017 年。此外,无需在输入中附加第 1 天。当日期不存在时,SimpleDateFormat 自动设置为 1:

// input format: MM/yy
SimpleDateFormat parser = new SimpleDateFormat("MM/yy");
// output format: yyyy-MM-dd
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(formatter.format(parser.parse("11/17"))); // 2017-11-01

PS: 如果你需要设置为另一天(1除外),你可以将日期设置为Calendar并更改它格式化前:

// parse the date
Date date = parser.parse("11/17");
// set to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// change to whatever day you want
cal.set(Calendar.DAY_OF_MONTH, whateverDayIwant);
// format it
System.out.println(formatter.format(cal.getTime()));

乔达时间

旧的 类(DateCalendarSimpleDateFormat)有 lots of problems and design issues,它们正在被新的 APIs.

我看到你在使用 Joda-Time,下面是如何使用这个 API。

在 Joda-Time 中,当您解析为 DateTime 时,它会为所有缺失的字段设置默认值(在本例中为天、小时、分钟等)。但是这个 API 还有很多其他类型最适合每个用例。

因为input只有年月,所以可以解析成org.joda.time.YearMonth,然后把day设置为1,这样就生成了org.joda.time.LocalDate,可以直接打印出来(如toString() 方法已经 returns 您想要的格式的日期):

DateTimeFormatter parser = DateTimeFormat.forPattern("MM/yy");
// parse to YearMonth
YearMonth ym = YearMonth.parse("11/17", parser);
// set day to 1
System.out.println(ym.toLocalDate(1)); // 2017-11-01

我更喜欢这种方法,因为您可以将其设置为您想要的任何一天,并且不需要创建一个完整的 DateTime 对象,其中包含您不 need/care 的字段(例如如小时、分钟等)。

如果你需要将这个值存储在一个String中,只需调用toString()方法:

// store "2017-11-01" in a String
String output = ym.toLocalDate(1).toString();

格式 yyyy-MM-ddtoString() 使用的默认格式。如果您需要不同的格式,可以将其传递给 toString():

// convert to another format (example: dd/MM/yyyy)
String output = ym.toLocalDate(1).toString("dd/MM/yyyy"); // 01/11/2017

或者您可以使用另一个 DateTimeFormatter:

// convert to another format (example: dd/MM/yyyy)
DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MM/yyyy");
String output = fmt.print(ym.toLocalDate(1)); // 01/11/2017

PS: dt.year().setCopy returns 一个 new 对象,正如你不t 将其分配给任何变量,此值将丢失 - 此方法不会更改原始 DateTime 对象,因此 dt 不会被其代码行更改。


Java新date/timeAPI

Joda-Time 处于维护模式,正在被新的 APIs 取代,所以我不建议用它开始一个新项目。即使在 joda's website 它说:"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".

如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。

如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.

如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it ).

下面的代码适用于两者。 唯一的区别是包名称(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但是类 和方法 names 相同。

代码与 Joda-Time 非常相似(API 不完全相同,但 they have lots of similarities)。您可以使用 Java 8 的 java.time.format.DateTimeFormatter 并将输入解析为 java.time.YearMonth(或者,在 Java 7 的 ThreeTen Backport 中,使用 org.threeten.bp.format.DateTimeFormatter 并解析为org.threeten.bp.YearMonth):

DateTimeFormatter parser = DateTimeFormatter.ofPattern("MM/yy");
YearMonth ym = YearMonth.parse("11/17", parser);
System.out.println(ym.atDay(1)); // 2017-11-01

如果你需要将这个值存储在一个String中,只需调用toString()方法:

// store "2017-11-01" in a String
String output = ym.atDay(1).toString();

格式 yyyy-MM-ddtoString() 使用的默认格式。如果你需要不同的格式,你可以使用另一个 DateTimeFormatter:

// convert to another format (example: dd/MM/yyyy)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String output = fmt.format(ym.atDay(1)); // 01/11/2017