如何使用java检测给定的日期格式
Posted
技术标签:
【中文标题】如何使用java检测给定的日期格式【英文标题】:How to detect the given date format using java 【发布时间】:2012-07-03 20:02:19 【问题描述】:我有一个获取字符串并将其更改为特定日期格式的方法,但问题是日期可以是任何格式 例如
16 July 2012
March 20 2012
2012 March 20
所以我需要检测字符串是哪种文件格式。
我使用下面的代码来测试它,但如果文件格式发生变化,我会得到异常。
private String getUpdatedDate(String updated)
Date date;
String formatedDate = null;
try
date = new SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH)
.parse(updated);
formatedDate = getDateFormat().format(date);
catch (ParseException e)
e.printStackTrace();
return formatedDate;
【问题讨论】:
***.com/questions/3389348/parse-any-date-in-java “任何格式”的范围相当大。这是否包括像03/04/05
这样的模棱两可的日期,这可能是取决于语言环境的任何顺序?这是否包括月份名称的本地化版本?
sdfonlinetester.info
【参考方案1】:
也许最简单的解决方案是构建一组您可以合理预期的日期格式,然后依次尝试输入每种格式。
您可能想要标记模棱两可的输入,例如2012/5/6 是 6 月 5 日还是 5 月 6 日?
【讨论】:
我赞成这个,因为我的想法是正确的,但为什么没有图书馆呢?这就是我正在寻找的。span> 【参考方案2】:BalusC 写了一个简单的DateUtil
,它适用于许多情况。您可能需要扩展它以满足您的要求。
这里是链接:https://balusc.omnifaces.org/2007/09/dateutil.html
以及你需要寻找的方法determineDateFormat()
【讨论】:
但是它不考虑像 1990 年 8 月 19 日这样的日期 @user2822178:您可以在DATE_FORMAT_REGEXPS
中再添加一个reg ex,例如^[a-z]3\\s\\d1,2[,]\\s\\d4$", "MMM dd, yyyy"
链接目前已断开
@BernhardWebstudio 修复了链接。谢谢。【参考方案3】:
如果您使用 Joda Time(btw 很棒的库),您可以很容易地做到这一点:
DateTimeParser[] dateParsers =
DateTimeFormat.forPattern("yyyy-MM-dd HH").getParser(),
DateTimeFormat.forPattern("yyyy-MM-dd").getParser() ;
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append(null, dateParsers).toFormatter();
DateTime date1 = formatter.parseDateTime("2012-07-03");
DateTime date2 = formatter.parseDateTime("2012-07-03 01");
【讨论】:
【参考方案4】:Apache commons 有一个实用方法来解决这个问题。 org.apache.commons.lang.time.DateUtils 类有一个方法 parseDateStrictly
public static Date parseDateStrictly(String str,
String[] parsePatterns)
throws ParseException
Parameters:
str - the date to parse, not null
parsePatterns - the date format patterns to use, see SimpleDateFormat, not null
通过尝试各种不同的解析器来解析表示日期的字符串。
解析将依次尝试每个解析模式。仅当解析整个输入字符串时,解析才被视为成功。如果没有匹配的解析模式,则抛出 ParseException。
解析器进行严格解析 - 它不允许诸如“1996 年 2 月 942 日”之类的日期。
【讨论】:
1996 年 2 月 942 日是一个日期? 942 代表什么??【参考方案5】:确定预期的格式,并尝试使用每种格式解析日期,一个接一个。只要其中一种格式无一例外地解析日期,就停止。
【讨论】:
【参考方案6】:Click to see the result
使用正则表达式解析日期字符串。此正则表达式可以检测任何类型的日期格式。这里的示例代码还不包括时间。您可以更改代码以添加更多日期部分,例如时间和时区...月份名称取决于系统的默认语言区域设置。
import java.io.IOException;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DateUtils
static String MONTH="";
static String dateRegEx="";
static Pattern DatePattern;
static HashMap<String, Integer> monthMap = new HashMap<String, Integer>();
static
initializeMonthName();
dateRegEx="(?i)(\\d1,4|"+MONTH+")[-|/|.|\\s+]?(\\d1,2|"+MONTH+")[-|/|.|,]?[\\s+]?(\\d1,4|"+MONTH+")[\\s+|\\t|T]?(\\d0,2):?(\\d0,2):?(\\d0,2)[.|,]?[\\s]?(\\d0,3)?([+|-])?(\\d0,2)[:]?(\\d0,2)[\\s+]?([A|P]M)?";
DatePattern = Pattern.compile(dateRegEx);
private static void initializeMonthName()
String[] monthName=getMonthString(true);
for(int i=0;i<12;i++)
monthMap.put(monthName[i].toLowerCase(), Integer.valueOf(i+1));
monthName=getMonthString(false);
for(int i=0;i<12;i++)
monthMap.put(monthName[i].toLowerCase(), Integer.valueOf(i+1));
Iterator<String> it = monthMap.keySet().iterator();
while(it.hasNext())
String month=it.next();
if(MONTH.isEmpty())
MONTH=month;
else
MONTH=MONTH + "|" + month;
public static boolean isInteger(Object object)
if(object instanceof Integer)
return true;
else
try
Integer.parseInt(object.toString());
catch(Exception e)
return false;
return true;
public static String[] getMonthString(boolean isShort)
DateFormatSymbols dfs = new DateFormatSymbols();
if (isShort)
return dfs.getShortMonths();
else
return dfs.getMonths();
public static int getMonthMap(String value)
if(monthMap.get(value)==null)
return 0;
return monthMap.get(value).intValue();
public static long parseDate(String value)
Matcher matcher = DatePattern.matcher(value);
int Year=0, Month=0, Day=0;
boolean isYearFound=false;
boolean isMonthFound=false;
boolean isDayFound=false;
if(matcher.find())
for(int i=1;i<matcher.groupCount();i++)
String data=matcher.group(i)==null?"":matcher.group(i);
if(data.equalsIgnoreCase("null"))
data="";
//System.out.println(String.valueOf(i) + ": " + data);
switch(i)
case 1:
if(!data.isEmpty())
if(isInteger(data))
Integer YMD = Integer.valueOf(data);
if(YMD==0)
return 0;
if(YMD>31)
Year = YMD.intValue();
isYearFound = true;
else if(YMD>12)
Day = YMD.intValue();
isDayFound = true;
else
Month=YMD.intValue();
isMonthFound=true;
else
Month = getMonthMap(data.toLowerCase());
if(Month==0)
return 0;
isMonthFound=true;
else
return 0;
break;
case 2:
if(!data.isEmpty())
if(isInteger(data))
Integer YMD = Integer.valueOf(data);
if(YMD==0)
return 0;
if(YMD>31)
if(isYearFound)
return 0;
Year = YMD.intValue();
isYearFound = true;
else if(YMD>12)
if(isDayFound)
return 0;
Day = YMD.intValue();
isDayFound = true;
else
if(isMonthFound)
Day=YMD.intValue();
isDayFound=true;
else
Month=YMD.intValue();
isMonthFound=true;
else
if(isMonthFound)
Day=Month;
isDayFound=true;
Month = getMonthMap(data.toLowerCase());
if(Month==0)
return 0;
isMonthFound=true;
else
return 0;
break;
case 3:
if(!data.isEmpty())
if(isInteger(data))
Integer YMD = Integer.valueOf(data);
if(YMD==0)
return 0;
if(YMD>31)
if(isYearFound)
return 0;
Year = YMD.intValue();
isYearFound = true;
else if(YMD>12)
if(isDayFound)
return 0;
Day = YMD.intValue();
isDayFound = true;
else
if(isMonthFound)
Day=YMD.intValue();
isDayFound=true;
else
Month = YMD.intValue();
isMonthFound=true;
else
if(isMonthFound)
Day=Month;
isDayFound=true;
Month = getMonthMap(data.toLowerCase());
if(Month==0)
return 0;
isMonthFound=true;
else
return 0;
break;
case 4:
//hour
break;
case 5:
//minutes
break;
case 6:
//second
break;
case 7:
//millisecond
break;
case 8:
//time zone +/-
break;
case 9:
//time zone hour
break;
case 10:
// time zone minute
break;
case 11:
//AM/PM
break;
Calendar c = Calendar.getInstance();
c.set(Year, Month-1, Day, 0, 0);
return c.getTime().getTime();
public static void main(String[] argv) throws IOException
long d= DateUtils.parseDate("16 July 2012");
Date dt = new Date(d);
SimpleDateFormat df2 = new SimpleDateFormat("d MMMM yyyy");
String dateText = df2.format(dt);
System.out.println(dateText);
d= DateUtils.parseDate("March 20 2012");
dt = new Date(d);
dateText = df2.format(dt);
System.out.println(dateText);
d= DateUtils.parseDate("2012 March 20");
dt = new Date(d);
dateText = df2.format(dt);
System.out.println(dateText);
【讨论】:
【参考方案7】: public static String detectDateFormat(Context context, String inputDate, String requiredFormat)
String tempDate = inputDate.replace("/", "").replace("-", "").replace(" ", "");
String dateFormat = "";
if (tempDate.matches("([0-12]2)([0-31]2)([0-9]4)"))
dateFormat = "MMddyyyy";
else if (tempDate.matches("([0-31]2)([0-12]2)([0-9]4)"))
dateFormat = "ddMMyyyy";
else if (tempDate.matches("([0-9]4)([0-12]2)([0-31]2)"))
dateFormat = "yyyyMMdd";
else if (tempDate.matches("([0-9]4)([0-31]2)([0-12]2)"))
dateFormat = "yyyyddMM";
else if (tempDate.matches("([0-31]2)([a-z]3)([0-9]4)"))
dateFormat = "ddMMMyyyy";
else if (tempDate.matches("([a-z]3)([0-31]2)([0-9]4)"))
dateFormat = "MMMddyyyy";
else if (tempDate.matches("([0-9]4)([a-z]3)([0-31]2)"))
dateFormat = "yyyyMMMdd";
else if (tempDate.matches("([0-9]4)([0-31]2)([a-z]3)"))
dateFormat = "yyyyddMMM";
else
try
String formattedDate = new SimpleDateFormat(requiredFormat, Locale.ENGLISH).format(new SimpleDateFormat(dateFormat).parse(tempDate));
Toast.makeText(context, formattedDate, Toast.LENGTH_SHORT).show();
return formattedDate;
catch (Exception e)
Toast.makeText(context, "Please check the date format", Toast.LENGTH_SHORT).show();
return "";
【讨论】:
【参考方案8】:我也遇到过这个问题,在某些地方:
-
我做了同样的事情,有一个符合我需要的格式集合。
更新了我的 sql 查询,它以我可以轻松解析的格式返回日期,例如在我的查询 TO_CHAR (o.CREATE_TS, 'MM-DD-YYYY') 中使用了这个
& 在转换为我所需的其他格式时,在 java 中使用“MM-dd-yyyy”来解析并更改为所需的格式。
希望#2 至少能在少数情况下对您有所帮助。
【讨论】:
以上是关于如何使用java检测给定的日期格式的主要内容,如果未能解决你的问题,请参考以下文章
如何从给定日期获得一个月的整数并打印为月份名称格式(“MMM”)
如何找出给定日期和开始和结束时间可用的所有持续时间:java