Java Android 将字符串解析为日期 - 未知模式字符“X”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28373610/
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
Android parse String to Date - unknown pattern character 'X'
提问by Matja? Mav
I have Service
fetch date string from web and then I want to pare it to Date
object. But somehow application crashes.
This is my string that I'm parsing: 2015-02-05T05:20:02+00:00
我已经Service
从网络上获取日期字符串,然后我想把它削成Date
对象。但不知何故应用程序崩溃。这是我正在解析的字符串:2015-02-05T05:20:02+00:00
onStartCommand()
启动命令()
String datetime = "2015-02-05T05:20:02+00:00";
Date new_date = stringToDate(datetime);
stringToDate()
字符串到日期()
private Date stringToDate(String s){
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
try{
return df.parse(s);
}catch(ParseException e){
e.printStackTrace();
}
return null;
}
LogCat:
日志猫:
02-06 20:37:02.008: E/AndroidRuntime(28565): FATAL EXCEPTION: main
02-06 20:37:02.008: E/AndroidRuntime(28565): Process: com.dotmav.runescapenotifier, PID: 28565
02-06 20:37:02.008: E/AndroidRuntime(28565): java.lang.RuntimeException: Unable to start service com.dotmav.runescapenotifier.GEService@384655b5 with Intent { cmp=com.dotmav.runescapenotifier/.GEService }: java.lang.IllegalArgumentException: Unknown pattern character 'X'
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2881)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.access00(ActivityThread.java:144)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.os.Handler.dispatchMessage(Handler.java:102)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.os.Looper.loop(Looper.java:135)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.main(ActivityThread.java:5221)
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.lang.reflect.Method.invoke(Native Method)
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.lang.reflect.Method.invoke(Method.java:372)
02-06 20:37:02.008: E/AndroidRuntime(28565): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-06 20:37:02.008: E/AndroidRuntime(28565): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-06 20:37:02.008: E/AndroidRuntime(28565): Caused by: java.lang.IllegalArgumentException: Unknown pattern character 'X'
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:314)
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.validatePattern(SimpleDateFormat.java:303)
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:356)
02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:249)
02-06 20:37:02.008: E/AndroidRuntime(28565): at com.dotmav.runescapenotifier.GEService.stringToDate(GEService.java:68)
02-06 20:37:02.008: E/AndroidRuntime(28565): at com.dotmav.runescapenotifier.GEService.onStartCommand(GEService.java:44)
02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2864)
02-06 20:37:02.008: E/AndroidRuntime(28565): ... 9 more
EDIT:onDestroy() set alarm for periodical update...
编辑:onDestroy() 为定期更新设置警报...
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.set(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (1000 * 60),
PendingIntent.getService(this, 0, new Intent(this, GEService.class), 0)
);
采纳答案by Rohit5k2
Remove "XXX" from
删除“XXX”
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
and everything would work fine.
一切都会好起来的。
Go through the list of symbols that can be used inside a SimpleDateFormat
constructor. Although the documentationshows the "XXX" format, this doesn't work on Android and will throw an IllegalArgumentException
.
查看可以在SimpleDateFormat
构造函数中使用的符号列表。尽管文档显示了“XXX”格式,但这在 Android 上不起作用,并且会抛出一个IllegalArgumentException
.
Probably you are looking for "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
可能你正在寻找 "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
Change your code to
将您的代码更改为
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
or
或者
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // if timezone is required
回答by Adam W
The error is saying that simpleDateFormat does not recognize the character X. If you are looking for milliseconds it is represented with the character S.
错误是说 simpleDateFormat 无法识别字符 X。如果您要查找毫秒,则它用字符 S 表示。
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
回答by Thanos
You are using the wrong date formatter.
您使用了错误的日期格式化程序。
Use this instead: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
改用这个: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
I think that android in contrast with Java 7 uses Z (as in Java 6) for timezones and not X. So, use thisfor your date formats.
我认为与 Java 7 相比,android 使用 Z(如在 Java 6 中)作为时区而不是 X。因此,将它用于您的日期格式。
回答by Alexander K
Since Z and XXX are different, I've implemented the following workaround:
由于 Z 和 XXX 不同,我实施了以下解决方法:
// This is a workaround from Z to XXX timezone format
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") {
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
StringBuffer rfcFormat = super.format(date, toAppendTo, pos);
return rfcFormat.insert(rfcFormat.length() - 2, ":");
}
@Override
public Date parse(String text, ParsePosition pos) {
if (text.length() > 3) {
text = text.substring(0, text.length() - 3) + text.substring(text.length() - 2);
}
return super.parse(text, pos);
}
}
回答by Sudhakar
The following class can be used to convert the string to date when pattern doesn't aware of it.
当模式不知道它时,以下类可用于将字符串转换为日期。
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* StringToDateFormater is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for
* formatting (date → text), parsing (text → date), and normalization.
*
* This class is mainly used for convert the date from string. It should be used only when date pattern doesn't aware of
* it.
*
*/
public class StringToDateFormater extends SimpleDateFormat {
private static final List<String> DATE_SUPPORTED_FORMAT_LIST = Arrays.asList("yyyyMMddHHmmss", "yyyyMMddHHmm",
"yyyyMMddHHmm", "yyyyMMddHH", "yyyyMMdd", "yyyyMMddHHmmssSS");
/**
*
*/
private static final long serialVersionUID = -1732857502488169225L;
/**
* @param pattern
*/
public StringToDateFormater() {
}
@Override
public Date parse(String source) {
Date date = null;
SimpleDateFormat dateFormat = null;
for (String format : DATE_SUPPORTED_FORMAT_LIST) {
dateFormat = new SimpleDateFormat(format);
try {
return dateFormat.parse(source);
} catch (Exception exception) {
}
}
return date;
}
}
回答by Narek
Android SimpleDateFormatis different from Java 7 SDK and does not support 'X' to parse ISO 8601. You can use the 'Z' or 'ZZZZZ' styles to format and programatically set the time zone to UTC. Here is a util class:
Android SimpleDateFormat与 Java 7 SDK 不同,不支持“X”解析 ISO 8601。您可以使用“Z”或“ZZZZZ”样式来格式化并以编程方式将时区设置为 UTC。这是一个 util 类:
public class DateUtil {
public static final String iso8601DatePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ";
public static final DateFormat iso8601DateFormat = new SimpleDateFormat(iso8601DatePattern);
public static final TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
static {
iso8601DateFormat.setTimeZone(utcTimeZone);
}
public static String formatAsIso8601(Date date) {
return iso8601DateFormat.format(date);
}
}
回答by flawyte
The Android version of SimpleDateFormat
doesn't support the X
pattern so XXX
won't work but instead you can use ZZZZZ
which does the same and outputs the timezone in format +02:00
(or -02:00
depending on the local timezone).
Android 版本SimpleDateFormat
不支持该X
模式,因此XXX
无法使用ZZZZZ
,但您可以使用which 执行相同操作并以格式+02:00
(或-02:00
取决于本地时区)输出时区。
回答by Basil Bourque
tl;dr
tl;博士
long millisecondsSinceEpoch = OffsetDateTime.parse( "2015-02-05T05:20:02+00:00" ).plusHour( 1 ).toInstant().toEpochMilli() // Warning: Possible loss of data in truncating nanoseconds to milliseconds. But not in this particular case.
Details
细节
Other answers are correct but now outdated. The old date-time classes are now legacy. Use java.time classes instead.
其他答案是正确的,但现在已经过时了。旧的日期时间类现在是遗留的。改用 java.time 类。
ISO 8601
ISO 8601
The input String is in standard ISO 8601 format. Parse directly, no need to define a formatting pattern as the java.time classes use ISO 8601 formats by default.
输入字符串采用标准 ISO 8601 格式。直接解析,无需定义格式化模式,因为 java.time 类默认使用 ISO 8601 格式。
OffsetDateTime
OffsetDateTime
The input includes an offset-from-UTC with the +00:00
so we can parse as an OffsetDateTime
object.
输入包括一个与 UTC 的偏移量,+00:00
因此我们可以将其解析为一个OffsetDateTime
对象。
String input = "2015-02-05T05:20:02+00:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input );
Math
数学
If you want to add an hour or a minute later to set an alarm, call the plus
methods.
如果您想添加一小时或一分钟后设置闹钟,请调用plus
方法。
OffsetDateTime minuteLater = odt.plusMinutes( 1 );
OffsetDateTime hourLater = odt.plusHours( 1 );
To get a count of milliseconds, go through the Instant
class. The Instant
class represents a moment on the timeline in UTCwith a resolution of nanoseconds. Asking for milliseconds means possible data lossas the nine digits of a decimal fraction get truncated to the three digits of decimal fraction.
要获得毫秒数,请查看Instant
课程。该Instant
级表示时间轴上的时刻UTC,分辨率为纳秒。要求毫秒意味着可能会丢失数据,因为十进制小数的九位数字被截断为小数的三位数。
long millisecondsSinceEpoch = odt.toInstant().toEpochMilli(); // Warning: Possible loss of data in truncating nanoseconds to milliseconds.
About java.time
关于 java.time
The java.timeframework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了旧的麻烦的日期时间类,例如java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to java.time.
现在处于维护模式的Joda-Time项目建议迁移到 java.time。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backportand further adapted to Androidin ThreeTenABP.
多的java.time功能后移植到Java 6和7在ThreeTen-反向移植并且还适于的Android在ThreeTenABP。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。
回答by Hiren Patel
Simple solution:
简单的解决方案:
Usethis yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ
使用这个yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ
Insteadof yyyy-MM-dd'T'HH:mm:ss.SSSXXX
相反的yyyy-MM-dd'T'HH:mm:ss.SSSXXX
Done.
完毕。
回答by suhasini
Use a SimpleDateFormat
to produce a properly formatted String
output:
使用 aSimpleDateFormat
生成格式正确的String
输出:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String formattedNow = simpleDateFormat.format(new Date(System.currentTimeMillis()));
Output : 2018-02-27T07:36:47.686Z
输出 : 2018-02-27T07:36:47.686Z