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

Bil*_*yfm 1 java date jodatime date-parsing simpledateformat

我需要将"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";
Run Code Online (Sandbox Code Playgroud)

和:

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);
}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么我需要在第二个appproach中使用这一行:

calendar.add(Calendar.YEAR, -100);
Run Code Online (Sandbox Code Playgroud)

他们俩都在工作.但我不确定是否有更好的解决方案.

小智 8

您无需在年份中添加值.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
Run Code Online (Sandbox Code Playgroud)

PS:如果您需要设置为另一天(除1之外),您可以将日期设置为a 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()));
Run Code Online (Sandbox Code Playgroud)

乔达时间

老班(Date,CalendarSimpleDateFormat)有很多问题设计问题,他们正在被新的API取代.

我已经看到你正在使用Joda-Time,所以这里是如何用这个API做的.

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

由于输入只有月份和年份,您可以将其解析为a org.joda.time.YearMonth,然后将日期设置为1.这将创建一个org.joda.time.LocalDate,可以直接打印(因为该toString()方法已经以您想要的格式返回日期):

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
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方法,因为您可以将其设置为您想要的任何日期,并且不需要创建包含DateTime您不需要/关心的字段的完整对象(例如小时,分钟等).

如果需要将此值存储在a中String,只需调用toString()方法:

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

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

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

或者你可以使用另一个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
Run Code Online (Sandbox Code Playgroud)

PS: dt.year().setCopy返回一个对象,因为你没有将它分配给任何变量,这个值就会丢失 - 这个方法不会改变原始DateTime对象,所以dt不会被它的代码行改变.


Java新的日期/时间API

Joda-Time处于维护模式,正在被新的API取代,因此我不建议使用它来启动新项目.甚至在joda的网站上也说:"请注意,Joda-Time被认为是一个很大程度上已经完成的项目.没有计划进行重大改进.如果使用Java SE 8,请迁移到java.time(JSR-310)." .

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

如果您使用的是Java 8,请考虑使用java.timeAPI.与旧的API相比,它更容易,更少出错并且更不容易出错.

如果您使用的是Java 6或7,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端.对于Android,你还需要ThreeTenABP(更多关于如何在这里使用它).

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

代码与Joda-Time非常相似(API不完全相同,但它们有很多相似之处).您可以使用Java 8 java.time.format.DateTimeFormatter并将输入解析为java.time.YearMonth(或者,在Java 7的ThreeTen Backport中,使用a org.threeten.bp.format.DateTimeFormatter并解析为a 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
Run Code Online (Sandbox Code Playgroud)

如果需要将此值存储在a中String,只需调用toString()方法:

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

格式yyyy-MM-dd是默认使用的格式toString().如果您需要不同的格式,可以使用另一种格式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
Run Code Online (Sandbox Code Playgroud)

  • 在我看来,java.time方法应该在你的答案中排在第一位. (2认同)