java Simpledateformat 不可解析的日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49192337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simpledateformat unparseable date
提问by Carl Bruiners
I have a String
in a database (match.getDate
) that has the following date format:
我String
在match.getDate
具有以下日期格式的数据库 ( ) 中有一个:
01/04/2018
01/04/2018
This is the date I want to format, stored as day/month/year. I want to format this for my Android app.
这是我要格式化的日期,存储为日/月/年。我想为我的 Android 应用程序格式化它。
I want to format the date into:
我想将日期格式化为:
Sun 01 Apr 2018
2018 年 4 月 1 日星期日
My code below:
我的代码如下:
SimpleDateFormat fDate = new SimpleDateFormat("dd/MM/yyyy");
try {
textViewDate.setText(fDate.parse(match.getDate()).toString());
} catch (ParseException ex) {
System.out.println(ex.toString());
}
This outputs:
这输出:
Sun Apr 08 00:00:00 GMT+00:00 2018.
2018 年 4 月 8 日星期日 00:00:00 GMT+00:00。
I have also tried "EE, MM d, yyyy"
, but it gives me:
我也试过"EE, MM d, yyyy"
,但它给了我:
java.text.ParseException: Unparseable date: "01/04/2018"
java.text.ParseException:无法解析的日期:“01/04/2018”
采纳答案by Harsh Patel
Use this date formatter method I have created
使用我创建的这个日期格式化方法
public static String dateFormater(String dateFromJSON, String expectedFormat, String oldFormat) {
SimpleDateFormat dateFormat = new SimpleDateFormat(oldFormat);
Date date = null;
String convertedDate = null;
try {
date = dateFormat.parse(dateFromJSON);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(expectedFormat);
convertedDate = simpleDateFormat.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return convertedDate;
}
and call this method like
并像这样调用这个方法
dateFormater(" 01/04/2018" , "EE dd MMM yyyy" , "dd/MM/yyyy")
and you will get the desired output
你会得到想要的输出
回答by shind
The other answers solved your problem, but I think it's important to know some concepts and why your first attempt didn't work.
其他答案解决了您的问题,但我认为了解一些概念以及为什么您的第一次尝试无效很重要。
There's a difference between a dateand a text that represents a date.
日期和表示日期的文本之间存在差异。
Example: today's date is March 9th 2018. That date is just a concept, an idea of "a specific point in our calendar system".
示例:今天的日期是2018 年 3 月 9 日。该日期只是一个概念,是“我们日历系统中的特定点”的想法。
The same date, though, can be representedin many formats. It can be "graphical", in the form of a circle around a number in a piece of paper with lots of other numbers in some specific order, or it can be in plain text, such as:
但是,相同的日期可以用多种格式表示。它可以是“图形化的”,形式为围绕一张纸上的一个数字和许多其他数字以特定顺序排列的圆圈的形式,或者它可以是纯文本,例如:
- 09/03/2018 (day/month/year)
- 03/09/2018 (monty/day/year)
- 2018-03-09 (ISO8601 format)
- March, 9th2018
- 9 de mar?o de 2018 (in Portuguese)
- 2018年3月5日 (in Japanese)
- and so on...
- 09/03/2018(日/月/年)
- 03/09/2018(月/日/年)
- 2018-03-09 ( ISO8601 格式)
- 2018 年3 月 9日
- 9 de mar?o de 2018(葡萄牙语)
- 2018年3月5日(日语)
- 等等...
Note that the text representations are different, but all of them represent the same date (the same value).
请注意,文本表示不同,但它们都表示相同的日期(相同的值)。
With that in mind, let's see how Java works with these concepts.
考虑到这一点,让我们看看 Java 如何处理这些概念。
- a text is represented by a
String
. This class contains a sequence of characters, nothing more. These characters can represent anything; in this case, it's a date - a date was initially represented by
java.util.Date
, and then byjava.util.Calendar
, but those classes are full of problemsand you should avoid them if possible. Today we have a better API for that.
- 文本由 a 表示
String
。这个类包含一个字符序列,仅此而已。这些字符可以代表任何东西;在这种情况下,这是一个约会 - 日期最初由 表示
java.util.Date
,然后由 表示java.util.Calendar
,但是这些类充满了问题,您应该尽可能避免使用它们。今天我们有一个更好的 API。
In Android, you can use the java.time
classes if available in the API level you're using, or the threeten backportfor API levels lower than that (check here how to use it). You'll have easier and more reliable tools to deal with dates.
在 Android 中,您可以使用在java.time
您正在使用的 API 级别中可用的类,或者对于低于该级别的 API 级别的三个反向移植(请在此处查看如何使用它)。您将拥有更简单、更可靠的工具来处理日期。
In your case, you have a String
(a text representing a date) and you want to convert it to another format. You must do it in 2 steps:
在您的情况下,您有一个String
(代表日期的文本)并且您想将其转换为另一种格式。您必须分两步完成:
- convert the
String
to some date-type (transform the text to numerical day/month/year values) - that's called parsing - convert this date-type value to some format (transform the numerical values to text in a specific format) - that's called formatting
- 将 转换
String
为某种日期类型(将文本转换为数字日/月/年值) - 这称为解析 - 将此日期类型值转换为某种格式(将数值转换为特定格式的文本)——这称为格式化
Why your attempts didn't work:
为什么您的尝试无效:
- the first attempt gave you the wrong format because you called
Date::toString()
method, which produces an output (a text representation) in that format (Sun Apr 08 00:00:00 GMT+00:00 2018
) - so the parsing was correct, but the formatting wasn't - in the second attempt, you used the output pattern (
EE dd MMM yyyy
, the one you should use for formatting) to parse the date (which caused theParseException
).
- 第一次尝试给了您错误的格式,因为您调用了
Date::toString()
method,它以该格式 (Sun Apr 08 00:00:00 GMT+00:00 2018
)生成输出(文本表示)-因此解析正确,但格式不正确 - 在第二次尝试中,您使用输出模式(
EE dd MMM yyyy
,您应该用于格式化的模式)来解析日期(导致ParseException
)。
For step 1, you can use a LocalDate
, a type that represents a date (day, month and year, without hours and without timezone), because that's what your input is:
对于第 1 步,您可以使用 a LocalDate
,一种表示日期(日、月和年,没有小时和时区)的类型,因为这就是您的输入:
String input = "01/04/2018";
DateTimeFormatter inputParser = DateTimeFormatter.ofPattern("dd/MM/yyyy");
// parse the input
LocalDate date = LocalDate.parse(input, inputParser);
That's more reliable than SimpleDateFormat
because it solves lots of strange bugs and problemsof the old API.
这比SimpleDateFormat
因为它解决了旧 API 的许多奇怪的错误和问题更可靠。
Now that we have our LocalDate
object, we can do step 2:
现在我们有了我们的LocalDate
对象,我们可以做第 2 步:
// convert to another format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EE dd MMM yyyy", Locale.ENGLISH);
String output = date.format(formatter);
Note that I used a java.util.Locale
. That's because the output you want has the day of week and month name in English, and if you don't specify a locale, it'll use the JVM's default (and who guarantees it'll always be English? it's better to tell the API which language you're using instead of relying on the default configs, because those can be changed anytime, even by other applications running in the same JVM).
请注意,我使用了一个java.util.Locale
. 那是因为你想要的输出有英文的星期几和月份名称,如果你不指定语言环境,它将使用 JVM 的默认值(谁保证它总是英文?最好告诉API 您使用的是哪种语言而不是依赖于默认配置,因为这些可以随时更改,即使是在同一 JVM 中运行的其他应用程序)。
And how do I know which letters must be used in DateTimeFormatter
? Well, I've just read the javadoc.
我怎么知道必须在 中使用哪些字母DateTimeFormatter
?好吧,我刚刚阅读了javadoc。
回答by Basil Bourque
tl;dr
tl;博士
LocalDate
.parse(
"01/04/2018" ,
DateTimeFormatter // Parses & generates text in various formats
.ofPattern( "dd/MM/uuuu" ) // Define a formatting pattern to match your input.
) // Returns a `LocalDate` object.
.toString() // Generates text in standard ISO 8601 format.
2018-04-01
2018-04-01
Use data types appropriately
适当使用数据类型
I have a String in a database (match.getDate) that has the following date format:
我在具有以下日期格式的数据库 (match.getDate) 中有一个字符串:
Do not store date-time values as text.
不要将日期时间值存储为文本。
You should be storing date-time values in a database using date-time data types. In standard SQL, a date-only value without time-of-day and without time zone is stored in a column of type DATE
.
您应该使用日期时间数据类型在数据库中存储日期时间值。在标准 SQL 中,没有时间和时区的仅日期值存储在类型为 的列中DATE
。
Another problem is that you are trying to represent a date-only value in Java class that represents a moment, a date with time-of-day in context of time zone or offset-from-UTC. Square peg, round hole. Using a date-only data types makes your problems go away.
另一个问题是您试图在 Java 类中表示一个仅日期的值,该值表示一个时刻,一个在时区上下文中带有时间的日期或与 UTC 的偏移量。方钉,圆孔。使用仅限日期的数据类型可以让您的问题消失。
java.time
时间
The other Answers used outmoded classes, years ago supplanted by the modern java.timeclasses built into Java 8 and later, and built into Android 26 and later. For earlier Java & Android, see links below.
其他答案使用过时的类,几年前被Java 8 及更高版本内置的现代java.time类取代,Android 26 及更高版本内置。对于早期的 Java 和 Android,请参阅下面的链接。
In Java, a date-only value without time-of-day and without time zone is represented by the LocalDate
class.
在 Java 中,没有时间和时区的仅日期值由LocalDate
类表示。
LocalDate ld = LocalDate.parse( "2020-01-23" ) ; // Parsing a string in standard ISO 8601 format.
For a custom formatting pattern, use DateTimeFormatter
.
对于自定义格式模式,请使用DateTimeFormatter
.
String input = "01/04/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;
Generate a string in standard ISO 8601 format.
生成标准 ISO 8601 格式的字符串。
String output = ld.toString() ;
Generate a string in your custom format.
以您的自定义格式生成一个字符串。
String output = ld.format( f ) ;
Tip: Use DateTimeFormatter.ofLocalizedDate
to automatically localize your output.
提示:DateTimeFormatter.ofLocalizedDate
用于自动本地化您的输出。
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*
classes.
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Most of the java.timefunctionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.timeclasses.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 大多数java.time功能在ThreeTen-Backport 中被反向移植到 Java 6 & 7 。
- 安卓
- 更高版本的 Android 捆绑实现java.time类。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
回答by kshetline
You need two date formatters here. One to parse the input, and a different formatter to format the output.
这里需要两个日期格式化程序。一个解析输入,一个不同的格式化程序来格式化输出。
SimpleDateFormat inDateFmt = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat outDateFmt = new SimpleDateFormat("EEE dd MMM yyyy");
try {
Date date = inDateFmt.parse(match.getDate());
textViewDate.setText(outDateFmt.format(date));
} catch (ParseException ex) {
System.out.println(ex.toString());
}
回答by Gokul Nath KP
Try with new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
试试 new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
Sample Code:
示例代码:
DateFormat originalFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
Date date = originalFormat.parse("01/04/2018");
String formattedDate = targetFormat.format(date); // Sun 01 Apr 2018
回答by akshay
Try this, you can create any date format you want with this
试试这个,你可以用这个创建任何你想要的日期格式
public String parseTime(String date){
SimpleDateFormat format = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss");
try {
Date date1 = format.parse(date.replace("T"," "));
String d= new SimpleDateFormat("yyyy/dd/MM HH:mm:ss").format(date1);
return d;
}catch (Exception e){
e.printStackTrace();
}
return "";
}
回答by Android Team
first of check your match.getDate() method which format given date if is given above define format date then used below code and show date in define above format ...
首先检查您的 match.getDate() 方法,如果上面给出了给定日期的格式,则定义格式日期然后在下面的代码中使用并以上面定义的格式显示日期...
String date="09/03/2018";
SimpleDateFormat parseDateFormat = new SimpleDateFormat("dd/MM/yyyy"); // if your match.getDate() given this format date.and if is given different format that time define that format.
DateFormat formatdate = new SimpleDateFormat("EEE dd MMM yyyy");
try {
Date date1=parseDateFormat.parse(date);
Log.d("New Date",formatdate.format(date1));
} catch (ParseException e) {
e.printStackTrace();
}
output:: Fri 09 Mar 2018
输出:2018 年 3 月 9 日星期五