Date 无法使用JodaTime分析日期

Date 无法使用JodaTime分析日期,date,jodatime,datetime-format,date-parsing,android-jodatime,Date,Jodatime,Datetime Format,Date Parsing,Android Jodatime,从昨天开始,我一直在尝试使用JodaTime解析一个简单的日期,但到目前为止我一直失败 以下是我试图解析的(随机)日期: 2017年9月14日(即使大写S也不会改变任何事情…) 这是我的密码 DateTimeFormatter dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd"); // The variable 'parsed' is a dynamic string. For now I set it to 2017-sept-

从昨天开始,我一直在尝试使用JodaTime解析一个简单的日期,但到目前为止我一直失败

以下是我试图解析的(随机)日期: 2017年9月14日(即使大写S也不会改变任何事情…)

这是我的密码

 DateTimeFormatter dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd");
 // The variable 'parsed' is a dynamic string. For now I set it to 2017-sept-14 
 DateTime dateTime = dateTimeFormat.parseDateTime(parsed);
 Log.d(TAG, "Parsed date = "+ dateTime.toString());
我有一个例外:

java.lang.IllegalArgumentException: Invalid format: "2017-sept-14" is malformed at "sept-14" at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945)
我在这里错过了什么

更新: 实际上,我从文本字段中得到的是上面的格式,即日期-月-日(根据月份的不同,月份长度为3或4个字符…)
因此,当我有2017年9月14日的时候,我想要得到的输出仅仅是2017年9月14日,如果你想保持模式,你需要一个月(09)的两位数。否则,将您的模式更改为
yyyy-MMMM-dd

,因此我不知道这是否正确,但这对我有效(我最终使用SimpleDataFormat…):


Joda Time接受短格式(在大多数语言中,通常为3个字母)或长格式(全名)的月份名称。您的输入似乎是英文的,有4个字母,这是不受支持的

如果可以操作输入,可以删除额外的字符,并确保月份名称仅包含3个字母

我还使用
java.util.Locale
指定月份名称为英语。如果不指定区域设置,它将使用系统默认设置,并且不能保证始终为英语,因此最好指定一个

我还将其解析为一个
LocalDate
,因为它的
toString()
方法已经生成了您想要的输出:

String input=“2017-9-14”;
输入=输入。替换(“九月”、“九月”);
DateTimeFormatter dateTimeFormat=dateTimeFormat.forPattern(“yyyy MMM dd”)。带有语言环境(Locale.ENGLISH);
LocalDate dateTime=dateTimeFormat.parseLocalDate(输入);
System.out.println(日期时间);
输出为:

2017-09-14

我假设区域设置为英语,但在爱沙尼亚区域设置中,九月的短月份名称为“sept”,因此您也可以这样做:

String input=“2017-9-14”;
input=input.toLowerCase();//et_EE区域设置只接受“sept”
DateTimeFormatter dateTimeFormat=dateTimeFormat.forPattern(“yyyy MMM dd”)
.withLocale(新语言环境(“et”、“EE”));
LocalDate dateTime=dateTimeFormat.parseLocalDate(输入);
System.out.println(日期时间);
或者您可以尝试使用系统的默认设置(根据您的评论,
SimpleDateFormat
适用于法语区域设置,因此上面的代码也有可能起作用)


Java新的日期/时间API Joda Time处于维护模式,正在被新的API所取代,因此我不建议使用它启动新项目。甚至在文章中也提到:“请注意,Joda Time被认为是一个基本上“完成”的项目。没有计划进行重大的增强。如果使用Java SE 8,请迁移到Java.Time(JSR-310)。”

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

在Android中,您可以使用,这是Java8新的日期/时间类的一个很好的后端口。要使它工作,您还需要(更多关于如何使用它的信息)

您可以创建格式化程序,设置区域设置并将其解析为
LocalDate

import org.threeten.bp.LocalDate;
导入org.threeten.bp.format.DateTimeFormatter;
导入org.threeten.bp.format.DateTimeFormatterBuilder;
DateTimeFormatter f=新的DateTimeFormatterBuilder()
//不区分大小写(因此它接受Sept、Sept等)
.parseCase不敏感()
//图案
.appendPattern(“yyyy MMM dd”)
//设置区域设置
.toFormatter(新语言环境(“et”、“EE”);
系统输出打印LN(LocalDate.parse(“2017-9-14”,f));
输出为:

2017-09-14

或者尝试使用系统的默认区域设置(只需调用
toFormatter()
,不带参数,它将使用系统默认设置)


或者,您可以创建自定义月份名称的映射,并在格式化程序中使用它。唯一的细节是,您必须用所有月份的值填充它。我将
Sept
放在9月份,您可以相应地填写其他月份:

//月份自定义名称的映射
Map monthNames=新的HashMap();
//输入输入中使用的名称
每月(1L,“一月”);
月放(2L,“2月”);
3月份(3L,“Mar”);
月平均投入(4L,“四月”);
蒙特纳姆斯。普特(5L,“五月”);
monthNames.put(6L,“Jun”);
月平均值(7升,“7月”);
8月份(8月8日);
月平均价格(9月9日);
月平均值(10升,“10月”);
11月11日;
12月份(12升,“12月”);
DateTimeFormatter fmt=新的DateTimeFormatterBuilder()
//不区分大小写(因此它接受Sept、Sept等)
.parseCase不敏感()
//年
.appendPattern(“yyyy-”)
//月份,使用自定义名称
.appendText(ChronoField.MONTH\u OF_YEAR,monthNames)
//一天
.appendPattern(“-dd”)
//创建格式化程序
.toFormatter();
字符串输入=“2017-9-14”;
System.out.println(LocalDate.parse(input,fmt));

Joda Time不提供简单的方法。唯一(复杂)的方法是定义自己的实现。你可能会从我那里找到一些灵感,如何在其他人身上实现它,然后:

DateTimeParser monthParser = ...; // left as exercise to you

DateTimeFormatter joda = 
  new DateTimeFormatterBuilder()
  .appendPattern("yyyy-")
  .append(monthParser)
  .append("-dd")
  .toFormatter();
LocalDate ld = joda.parseLocalDate("2017-sept-14");
我不知道为什么雨果建议基于地图查找自定义名称的答案对你不起作用。可能月份名称是可变的,而不是固定的(对于同一个月)。也许你只是想检查月份名称是否以相同的前缀开头。如果是这样,那么my lib可能会对您有所帮助,因为它管理更多的格式化/解析属性来控制解析,请参见以下简短示例(如果存在,它还管理其他尾随点):

String s=“2017-9-14”;
计时表f=
计时表
.setUp(PlainDate.class,新的java.util.Locale(“fr”、“fr”))
.addPattern(“uu-MMM”,PatternType.CLDR)
.skipUnknown(c->c=='',1)
.addPattern(“-dd”,Pat
DateTimeParser monthParser = ...; // left as exercise to you

DateTimeFormatter joda = 
  new DateTimeFormatterBuilder()
  .appendPattern("yyyy-")
  .append(monthParser)
  .append("-dd")
  .toFormatter();
LocalDate ld = joda.parseLocalDate("2017-sept-14");
String s = "2017-sept.-14";
ChronoFormatter<PlainDate> f =
  ChronoFormatter
    .setUp(PlainDate.class, new java.util.Locale("fr", "FR"))
    .addPattern("uuuu-MMM", PatternType.CLDR)
    .skipUnknown(c -> c == '.', 1)
    .addPattern("-dd", PatternType.CLDR)
    .build()
    .with(net.time4j.format.Attributes.PARSE_CASE_INSENSITIVE, true)
    .with(net.time4j.format.Attributes.PARSE_PARTIAL_COMPARE, true);
System.out.println(f.parse(s)); // 2017-09-14