我有一个工具,它似乎给了我日期而没有指定我需要转换的年份,我使用Java来完成任务(实际上是Groovy,但在这种情况下足够接近)。一个示例日期是" 13月12日12:00:00",这应该引用12/13/2011,因为年份未指定,它是2011.以下Groovy脚本可以解决这个问题:
import java.text.*
println new SimpleDateFormat("dd MMM HH:mm:ss").parse("13 Dec 12:00:00")
我对这个脚本的问题是SimpleDateFormat似乎在转换后的1970年没有设置。我可以明确地将它设置为2011年,因为那是当前年份,但是当前年份与设定的日期之间似乎存在一些滞后,因此当新年到来时,此脚本将在该滞后时间出错。我该如何解决这个问题呢?一种解决方案是检查当前年份的日期是否已经过去,然后使用去年,但我希望有一个更简单的解决方案(或说“如果不是最简单的解决方案”)。
答案 0 :(得分:5)
您可以使用java.util.Calendar
获取当前年份,如下例所示。
Calendar.getInstance ().get (Calendar.YEAR);
示例摘录
OP详细阐述了他的问题,因此这个片段已被重写以符合他的需要。 public static String fixDate (String data) throws Exception {
SimpleDateFormat dateInputFormat = new SimpleDateFormat("dd MMM HH:mm:ss");
SimpleDateFormat dateOutputFormat = new SimpleDateFormat("yyyy dd MMM HH:mm:ss");
Calendar currentCal = Calendar.getInstance ();
Calendar parsedCal = Calendar.getInstance ();
int CAL_YEAR = Calendar.YEAR;
parsedCal.setTime (dateInputFormat.parse (data));
parsedCal.set (CAL_YEAR, currentCal.get (CAL_YEAR));
if (parsedCal.after (currentCal))
parsedCal.set (CAL_YEAR, parsedCal.get (CAL_YEAR) - 1);
// Date parsedDate = parsedCal.getTime ();
return dateOutputFormat.format (parsedCal.getTime ());
}
public static void main (String[] args) throws Exception {
System.out.println (fixDate ("13 Dec 12:00:00"));
System.out.println (fixDate ("31 Dec 12:00:00"));
}
输出
2011 13 Dec 12:00:00
2010 31 Dec 12:00:00
请注意抛出Exceptions
!
答案 1 :(得分:5)
现代答案(从2014年开始有效):我首先声明一个辅助方法:
private static LocalDateTime parseWithDefaultYear(String stringWithoutYear, int defaultYear) {
DateTimeFormatter parseFormatter = new DateTimeFormatterBuilder()
.appendPattern("dd MMM HH:mm:ss")
.parseDefaulting(ChronoField.YEAR, defaultYear)
.toFormatter(Locale.ENGLISH);
LocalDateTime dateTime = LocalDateTime.parse(stringWithoutYear, parseFormatter);
return dateTime;
}
然后我们可以这样做:
ZoneId zone = ZoneId.of("America/Argentina/Jujuy");
String stringWithoutYear = "13 Dec 12:00:00";
LocalDateTime now = LocalDateTime.now(zone);
int defaultYear = now.getYear();
LocalDateTime dateTime = parseWithDefaultYear(stringWithoutYear, defaultYear);
if (dateTime.isAfter(now)) { // in the future
defaultYear--;
dateTime = parseWithDefaultYear(stringWithoutYear, defaultYear);
}
System.out.println(dateTime);
今天(2018年6月)运行时,会打印出来:
2017-12-13T12:00
您可能会问我为什么要第二次使用新的格式化程序解析,以防第一次尝试在将来提供日期。减去1年不是更简单吗?虽然java.time
肯定对此有很好的支持,但我选择了第二次解析以更好地处理2月29日的闰年。想象一下,代码是在2021年的前几个月运行的,字符串是29 Feb 12:00:00
。由于2021年不是闰年,Java将选择2月28日,即该月的最后一天。减去1年将给2020年2月28日,这是不正确的,因为2020年 是闰年。相反,我对2020年作为默认年份的新解析给出了正确的2020年2月29日。
消息:
Date
,SimpleDateFormat
,Calendar
和GregorianCalendar
现在已经过时了,所以我建议避免使用它们。现代课程通常更方便程序员,并且带来更少的令人不快的惊喜。Locale.ENGLISH
。由于您认为可以安全地假设日期在去年之内,我邀请您考虑是否也可以安全地假设它在过去的4,6或8个月内,例如?如果是这样,测试是否是这种情况将为您提供更好的验证:
if (dateTime.isBefore(now.minusMonths(5))) {
throw new IllegalArgumentException("Not within the last 5 months: " + stringWithoutYear);
}
答案 2 :(得分:1)
String date_string = "13 Dec 12:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM HH:mm:ss yyyy");
Date date = sdf.parse(date_string + " " + Calendar.getInstance ().get(Calendar.YEAR));
System.out.println(date);
<强>输出:强>
Tue Dec 13 12:00:00 IST 2011
答案 3 :(得分:0)
最简单的解决方案是在解析之前将当前年份附加到日期字符串。例如:
def currentYear = new Date()[Calendar.YEAR]
def d = Date.parse("dd MMM HH:mm:ss yyyy", "13 Dec 12:00:00 " + currentYear)
println d
===> Tue Dec 13 12:00:00 MST 2011
答案 4 :(得分:0)
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar goal= new GregorianCalendar(now.get(Calendar.YEAR), month-1, day);
if (goal.after(now)) {
goal.add(Calendar.YEAR, -1);
}
目标有你的更正日期。