我需要将"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);
}
我不确定为什么我在第二个appproach中需要这一行:
calendar.add(Calendar.YEAR, -100);
他们两个都在工作。但我不确定是否有更好的解决方案。
答案 0 :(得分:7)
您不需要为年份添加值。 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()));
旧类(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design issues,并且它们被新API取代
我已经看到你正在使用Joda-Time,所以这里有如何使用这个API。
在Joda-Time中,当您解析为DateTime
时,它会为所有缺失的字段设置默认值(在本例中为日,小时,分钟等)。但是这个API有很多其他类型,可以最适合每个用例。
由于输入只有月份和年份,您可以将其解析为org.joda.time.YearMonth
,然后将日期设置为1.这将创建org.joda.time.LocalDate
,可以直接打印(如{ {1}}方法已经以您想要的格式返回日期:
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
对象(例如小时,分钟等)。
如果您需要将此值存储在DateTime
中,只需调用String
方法:
toString()
格式// store "2017-11-01" in a String
String output = ym.toLocalDate(1).toString();
是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
:
DateTimeFormatter
PS: // 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
会返回新对象,因为您没有将其分配给任何变量,此值将丢失 - 此方法不会更改原始dt.year().setCopy
对象,因此DateTime
不会被其代码行更改。
Joda-Time处于维护模式,正在被新API取代,所以我不建议用它来启动新项目。即使在joda's website它也说:"请注意,Joda-Time被认为是一个很大程度上“完成”的项目。没有计划重大改进。如果使用Java SE 8,请迁移到java.time(JSR-310)。" 。
如果您不能(或者不想)从Joda-Time迁移到新API,您可以忽略此部分。
如果您使用 Java 8 ,请考虑使用new java.time
API。它更容易,less bugged and less error-prone than the old APIs。
如果您使用 Java 6或7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,您还需要ThreeTenABP(更多关于如何使用它here)。
以下代码适用于两者。
唯一的区别是包名称(在Java 8中为dt
而在ThreeTen Backport(或Android的ThreeTenABP中)为java.time
),但类和方法名称是相同的。
代码与Joda-Time非常相似(API不完全相同,但是they have lots of similarities)。您可以使用Java 8的org.threeten.bp
并将输入解析为java.time.format.DateTimeFormatter
(或者,在Java 7的ThreeTen Backport中,使用java.time.YearMonth
并解析为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-dd
使用的默认格式。如果您需要其他格式,可以使用其他toString()
:
DateTimeFormatter
答案 1 :(得分:0)
您可以定义两个实用程序方法,一个将字符串转换为日期,另一个将其转换回字符串。
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
如果您只打算将第一个字符串类型转换为第二个类型,则可以将它们组合在一起,但我喜欢将它们分开,以防我需要直接来自日期对象的字符串或字符串中的日期对象。