[英]How do I simply parse a date without a year specified?
我有一個工具,它似乎給了我日期,但沒有指定我需要轉換的年份,我正在使用 Java 來完成這項任務(實際上是 Groovy,但在這種情況下足夠接近)。 一個示例日期是“13 Dec 12:00:00”,它應該是指 2011 年 12 月 13 日,因為未指定年份並且它是 2011 年。以下 Groovy 腳本可以解決問題:
import java.text.*
println new SimpleDateFormat("dd MMM HH:mm:ss").parse("13 Dec 12:00:00")
我對這個腳本的問題是 SimpleDateFormat 似乎在轉換后將年份設置為 1970 年。 我可以將其明確設置為 2011 年,因為那是當前年份,但當前年份和設置的日期之間似乎存在一些滯后,所以當新年到來時,這個腳本會因為滯后時間而出錯。 我怎樣才能簡單地修復它? 一種解決方案是檢查當前年份的日期是否在現在之后,然后使用去年,但我希望存在一個更簡單的解決方案(或者說如果沒有,那就是最簡單的)。
現代答案(自 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); }
您可以使用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 年 12 月 13 日 12:00:00
2010 年 12 月 31 日 12:00:00
記住要注意拋出的Exceptions
!
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
最簡單的解決方案是在解析之前將當前年份附加到日期字符串。 例如:
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
GregorianCalendar now = new GregorianCalendar();
GregorianCalendar goal= new GregorianCalendar(now.get(Calendar.YEAR), month-1, day);
if (goal.after(now)) {
goal.add(Calendar.YEAR, -1);
}
目標有您的更正日期。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.