我对当前的UTC时间毫秒不感兴趣,也不需要弄乱时区。我的原始日期已存储为UTC时间戳。
我在UTC时间存储在数据库中的日期,“2012-06-14 05:01:25”。 我对日期时间不感兴趣,只是它的日期部分。因此,在使用Java检索日期并排除小时,分钟和秒后 - 我留下了“2012-06-14”。
如何将其转换为UTC毫秒?
答案 0 :(得分:11)
最简单的方法可能是使用SimpleDateFormat
,并适当设置了时区:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = format.parse(text);
long millis = date.getTime();
(此处设置时区是重要的位,否则它会将值解释为 local 时区。)
或者,如果您正在做一些不那么简单的事情,请使用Joda Time这是一个更好的日期/时间API。特别是,SimpleDateFormat
不是线程安全的,而DateTimeFormatter
是:
// This can be reused freely across threads after construction.
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withLocale(Locale.US)
.withZoneUTC();
// Option 1
DateTime datetime = formatter.parseDateTime(text);
long millis = dateTime.getMillis();
// Option 2, more direct, but harder to diagnose errors
long millis = formatter.parseMillis(text);
到目前为止,我们已经解析了整个整体架子。忽略日期部分的最简单方法就是将其四舍五入 - 毕竟,Java没有观察到闰秒,所以我们可以截断它:
long millisPerDay = 24L * 60L * 60L * 1000L; // Or use TimeUnit
long dayMillis = (millis / millisPerDay) * millisPerDay;
那将“向1970年前进”,所以如果你在 1970之前有一个日期它会转到当天的结束 - 但我怀疑这不太可能是问题
使用Joda Time版本,您可以使用它:
DateTime dateTime = formatter.parseDateTime(text);
long millis = dateTime.toLocalDate().getLocalMillis();
我个人不认为只需要一个子串。即使你实际上并不感兴趣保留小时/分钟/秒,我认为解析你已经给出的内容并且然后丢弃信息是合适的。除了其他任何东西,它会使你的代码在错误的数据中适当地失败,例如
"2012-06-100"
或
"2012-06-14 25:01:25"
表示无论是什么为您提供数据都存在问题,最好发现这一点,而不是盲目地继续,因为前10个字符都没问题。
答案 1 :(得分:1)
answer by Jon Skeet是正确的。并且他提出了一个很好的观点,即在解析时包括而不是截断时间信息。
然而,他的代码可以简化。特别是因为Joda-Time在最新版本中获得了一个重要的新方法:withTimeAtStartOfDay
。此方法取代了现在已弃用的所有“午夜”相关类和方法。
指定Locale是一个好习惯,如他的代码所示。但在这种特殊情况下,不需要Locale。
他的回答正确地表明了Joda-Time库,远远优于使用java.util.Date,.Calendar和java.text.SimpleTextFormat。这些课程出了名的麻烦,应该避免。而是使用Joda-Time或Java 8中内置的新java.time package(受Joda-Time启发,由JSR 310定义)。
如果您想要的是毫秒数,则不能忽略时间 - 自{ - 3}}。我怀疑你想要的是把时间改成一天的第一时刻。在UTC中,这总是表示时间00:00:00.000
。但请注意,在本地时区,由于epoch和可能的其他异常,第一时刻可能是不同的时间。
您的字符串几乎采用标准Daylight Saving Time格式,但我们需要在中间交换T
空格。然后我们可以将结果字符串直接提供给Joda-Time,因为Joda-Time默认使用内置ISO 8601标准字符串。
以下示例代码假定您的问题的意图是将字符串解析为formatters时区中的日期时间值,将时间调整为当天的第一时刻,然后转换为自UTC以来的几毫秒(UTC中的1970年初)。
String inputRaw = "2012-06-14 05:01:25";
String input = inputRaw.replace( " ", "T" ); // Replace SPACE with a 'T'.
DateTime dateTime = new DateTime( input, DateTimeZone.UTC ); // Parse, assuming UTC.
DateTime dateTimeTopOfTheDay = dateTime.withTimeAtStartOfDay(); // Adjust to first moment of the day.
long millisecondsSinceUnixEpoch = dateTimeTopOfTheDay.getMillis(); // Convert to millis. Use a 'long', not an 'int'.
答案 2 :(得分:1)
我正在提供现代答案。这些天(以及最近几年),您应该使用java.time(现代的Java日期和时间API)进行日期和时间工作。从JDBC 4.2开始,您可以直接从数据库中检索java.time对象(也可以将它们存储到数据库中)。一个现代的JPA实现(至少从Hibernate 5起就是Hibernate)将很乐意做同样的事情。因此,请忘记大多数旧答案中使用的SimpleDateFormat
,Date
和其他旧类。上面提到的设计不好,并且java.time更好用。
我还建议您不要从数据库中检索UTC时间作为字符串。如果SQL中的数据类型为timestamp with time zone
(建议使用UTC时间),请检索OffsetDateTime
。例如:
PreparedStatement pStmt = yourDatabaseConnection
.prepareStatement("select utc_time from your_table where id = 7;");
ResultSet rs = pStmt.executeQuery();
if (rs.next()) {
OffsetDateTime utcDateTime = rs.getObject("utc_time", OffsetDateTime.class);
long millisecondsSinceEpoch = utcDateTime.truncatedTo(ChronoUnit.DAYS)
.toInstant()
.toEpochMilli();
System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
}
如果SQL中的类型是没有时区的dateTime
或timestamp
,我们可能需要检索一个LocalDateTime
(具体取决于您的JDBC驱动程序和数据库的时区)会话)。它以相同的方式进行。要将LocalDateTime
转换为OffsetDateTime
,请参见下面的转换。
如果您无法避免像问题中那样将UTC时间作为字符串获取,请将其解析为LocalDateTime
并从那里进行转换。例如:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
String utcTimeString = "2012-06-14 05:01:25";
long millisecondsSinceEpoch = LocalDateTime.parse(utcTimeString, formatter)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
System.out.println("Milliseconds since the epoch: " + millisecondsSinceEpoch);
输出:
自纪元以来的毫秒数:1339650085000
答案 3 :(得分:0)
将Date对象与SimpleDateFormat结合使用。
在Date中有一个名为getTime()的方法,它将为您返回毫秒。
解决问题的示例:
Date truc = new SimpleDateFormat( "y-m-d").parse( "2010-06-14");
System.out.println(truc.getTime());
答案 4 :(得分:0)
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd"); //or whatever format you have
Date t = ft.parse('2014-03-20');
String result = String.format("%tQ", t);
System.out.printf("%tQ", t);
这里有两种方法:
答案 5 :(得分:-1)
我使用简单直接的方法:
Date date = new Date(utcDateInString);
long utcDateInMilliSeconds = date.getTime();