我正在使用SimpleDateFormat
对象和Date
对象,如下所示。问题是Date
对象显示错误的日期,这与原始字符串相距几分钟。 Date
对象似乎在调试器中以总毫秒数存储时间。
关于这个问题的任何想法?
import java.text.SimpleDateFormat;
import java.util.Date;
Date played_at_local;
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ");
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-05:00");
//played_at_local shows "Mon Apr 11 22:35:29 America/Chicago 2011" in debugger
答案 0 :(得分:15)
尝试从格式字符串中删除小数秒。我刚遇到同样的问题,但格式略有不同。我的输入格式不是ISO格式(没有“T”,没有“Z”),但症状是相同的 - 时间被一些随机数分钟和秒关闭,但其他一切都很好。这就是我的日志结果:
使用小数秒格式时:
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
# Parsed date: 2011-05-27 17:11:15.271816 => Fri May 27 17:15:46 EDT 2011
# Parsed date: 2011-05-27 17:09:37.750343 => Fri May 27 17:22:07 EDT 2011
# Parsed date: 2011-05-27 17:05:55.182921 => Fri May 27 17:08:57 EDT 2011
# Parsed date: 2011-05-27 16:55:05.69092 => Fri May 27 16:56:14 EDT 2011
# Parsed date: 2011-05-27 16:38:35.50348 => Fri May 27 16:39:25 EDT 2011
我通过从格式中删除小数秒来修复它。
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
# Parsed date: 2011-05-27 17:11:15.271816 => Fri May 27 17:11:15 EDT 2011
# Parsed date: 2011-05-27 17:09:37.750343 => Fri May 27 17:09:37 EDT 2011
# Parsed date: 2011-05-27 17:05:55.182921 => Fri May 27 17:05:55 EDT 2011
# Parsed date: 2011-05-27 16:55:05.69092 => Fri May 27 16:55:05 EDT 2011
# Parsed date: 2011-05-27 16:38:35.50348 => Fri May 27 16:38:35 EDT 2011
我认为发生的是输入字符串的“小数秒”部分太长(在OP示例中也是如此)。它似乎只期待三个小数位。如果你做数学运算(参加第一个例子):
271816 / 1000
答案 1 :(得分:1)
试试这个,为我工作 Z 应该在日期使用,或从格式字符串中删除
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'");
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726Z-05:00");
答案 2 :(得分:1)
您的代码中存在三个主要问题:
.SSSSSS
用于几分之一秒,而 SimpleDateFormat
不支持超过毫秒 (.SSS
) 的精度。这也意味着您需要将几分之一秒的数字限制为三。Z
来解析时区偏移量 -05:00
而用于此的 correct pattern 是 XXX
。hh
以 24 小时制格式,而正确的模式是 HH
。符号 hh
用于 12 小时制(即上午/下午)格式的时间。除此之外,我建议您始终将 Locale
与日期解析/格式化 API 一起使用,因为日期时间字符串的部分在不同的 Locale
中以不同的方式表示。
演示:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
Date date = sdf.parse("2011-04-11T22:27:18.491-05:00");
// Print the default string i.e. Date#toString
System.out.println(date);
// Print the date-time in a custom format
sdf.setTimeZone(TimeZone.getTimeZone("GMT-05:00"));
System.out.println(sdf.format(date));
}
}
输出:
Tue Apr 12 04:27:18 BST 2011
2011-04-11T22:27:18.491-05:00
关于旧日期时间 API 的一些事实:
java.util.Date
对象不是像 modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1, 1970, 00:00:00 GMT
(或 UTC)。当您打印 java.util.Date
的对象时,它的 toString
方法返回 JVM 时区中的日期时间,从这个毫秒值计算出来。如果您需要在不同的时区打印日期时间,则需要将时区设置为 SimpleDateFormat
并从中获取格式化的字符串。java.util
日期时间 API 及其格式 API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到 modern date-time API* 。使用现代日期时间 API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2011-04-11T22:27:18.491726-05:00");
// Print the default string i.e. OffsetDateTime#toString
System.out.println(odt);
// Print the date-time in a custom format. Note: OffsetDateTime#toString drops
// seconds if it is zero
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXX");
System.out.println(dtf.format(odt));
}
}
输出:
2011-04-11T22:27:18.491726-05:00
2011-04-11T22:27:18.491726-05:00
注意:对于符号 DateTimeFormatter
,u
表示年,而符号 y
表示年时代。在 [AD][2] 时代,它对一年没有任何影响,但在 BC 时代,它对一年很重要。查看 this answer 以了解更多信息。
从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。
答案 3 :(得分:0)
05:00 -->> 0500
和
hh --> HH // error not because of this ,but date is in 24hr format.
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-05:00");
应
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-0500");
答案 4 :(得分:0)
您可以尝试以下方法: http://docs.oracle.com/javase/6/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String)
关键是小数位是可选的,您可以使用其中的可变数字。但是,这似乎并未考虑时区。
来自文档:
valueOf
public static Timestamp valueOf(String s)
Converts a String object in JDBC timestamp escape format to a Timestamp value.
Parameters:
s - timestamp in format yyyy-mm-dd hh:mm:ss[.f...]. The fractional seconds may be omitted.
Returns:
corresponding Timestamp value
Throws:
IllegalArgumentException - if the given argument does not have the format yyyy-mm-dd hh:mm:ss[.f...]
答案 5 :(得分:0)
试试这个:
dTime = new SimpleDateFormat("HH:mm:ss:SS");
String sTime = (dTime.format(new java.util.Date())).toString();
希望这个帮助
答案 6 :(得分:0)
SimpleDateFormat
无法正确解析日期时间字符串。另一方面,现代的Java日期和时间API java.time支持开箱即用的格式。
import org.threeten.bp.OffsetDateTime;
String dateTimeString = "2011-04-11T22:27:18.491726-05:00";
OffsetDateTime playedAtLocal = OffsetDateTime.parse(dateTimeString);
System.out.println("Parsed into " + playedAtLocal);
输出为:
解析为2011-04-11T22:27:18.491726-05:00
SimpleDateFormat
仅支持毫秒,仅精确到秒的三位小数,而不是2,不是4,不是6(诚然,我不确定某些Android版本的SimpleDateFormat
版本是否可以做到更好,但您的问题表明您的版本不能)。 SimpleDateFormat
也是非常麻烦且长期过时的,因此您还是不想使用它。
java.time更好用。您会注意到,我们甚至不需要显式的格式化程序,因此不需要编写格式模式字符串,这始终是容易出错的任务。您的日期时间字符串为ISO 8601格式,并且java.time类将ISO 8601解析为其默认值。
是的,java.time在较新和较旧的Android设备上均可正常运行。它只需要至少 Java 6 。
org.threeten.bp
导入日期和时间类。java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。