将UTC日期转换为毫秒

时间:2012-08-22 21:06:24

标签: java time utc milliseconds

我对当前的UTC时间毫秒不感兴趣,也不需要弄乱时区。我的原始日期已存储为UTC时间戳。

我在UTC时间存储在数据库中的日期,“2012-06-14 05:01:25”。 我对日期时间不感兴趣,只是它的日期部分。因此,在使用Java检索日期并排除小时,分钟和秒后 - 我留下了“2012-06-14”。

如何将其转换为UTC毫秒?

6 个答案:

答案 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和可能的其他异常,第一时刻可能是不同的时间。

ISO 8601

您的字符串几乎采用标准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和JDBC 4.2

我正在提供现代答案。这些天(以及最近几年),您应该使用java.time(现代的Java日期和时间API)进行日期和时间工作。从JDBC 4.2开始,您可以直接从数据库中检索java.time对象(也可以将它们存储到数据库中)。一个现代的JPA实现(至少从Hibernate 5起就是Hibernate)将很乐意做同样的事情。因此,请忘记大多数旧答案中使用的SimpleDateFormatDate和其他旧类。上面提到的设计不好,并且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中的类型是没有时区的dateTimetimestamp,我们可能需要检索一个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);

这里有两种方法:

  1. 您将结果毫秒放入变量结果
  2. 直接打印。

答案 5 :(得分:-1)

我使用简单直接的方法:

Date date = new Date(utcDateInString);
long utcDateInMilliSeconds = date.getTime();