代码之家  ›  专栏  ›  技术社区  ›  Mark Smith

Java-SimpleDataFormat格式化程序以毫秒为单位返回历元时间[重复]

  •  4
  • Mark Smith  · 技术社区  · 7 年前

    一般来说,我对Java和编码非常陌生——我有一些代码以以下格式返回时间戳 yyyy.MM.dd HH:mm:ss:ms

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
    

    这将返回:

    2017.07.19 11:42:30:423
    

    有没有办法编辑上面的“SimpleDataformat格式化程序”代码,将日期/时间作为包含毫秒的历元时间戳返回,以便将返回的值格式化为如下格式?

    1500464550423
    

    ("yyyy.MM.dd HH:mm:ss:sss") 部分 SimpleDateFormat formatter

    非常感谢您的帮助或建议。

    谢谢

    6 回复  |  直到 7 年前
        1
  •  6
  •   Anonymous    7 年前

    SimpleDateFormat

    因此,我建议您改用现代Java日期和时间API(我有意逐字使用您的格式模式字符串):

        String receivedTimetamp = "2017.07.19 11:42:30:423";
        DateTimeFormatter parseFormatter
                = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:sss");
        LocalDateTime dateTime = LocalDateTime.parse(receivedTimetamp, parseFormatter);
        System.out.println(dateTime);
    

    此代码引发 IllegalArgumentException: Too many pattern letters: s the documentation 会告诉你小写字母 s S

        DateTimeFormatter parseFormatter
                = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
    

    现在代码打印出来了 2017-07-19T11:42:30.423

    要转换为毫秒,我们仍然缺少一条关键信息:时间戳应该在什么时区进行解释?我认为两个明显的猜测是UTC和您的本地时区(我不知道)。尝试UTC:

        System.out.println(dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli());
    

    这会产生 1500464550423 ,这是您要的号码。我想已经完成了。

    如果您希望使用JVM时区设置,请使用 .atZone(ZoneId.systemDefault()) .atOffset(ZoneOffset.UTC) ,但请注意,设置可能会被同一JVM中运行的其他软件更改,因此这是脆弱的。

        2
  •  2
  •   Community CDub    5 年前

    documentation of SimpleDateFormat .对应于 是一个 S ,而 s 通常不会抱怨并尝试解析 423

    无论如何 日期格式 只解析一个 String 到a java.util.Date 或格式化 Date 到a 一串 。如果您想要历元毫秒值,必须从 对象:

    // input string
    String s = "2017.07.19 11:42:30:423";
    // use correct format ('S' for milliseconds)
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
    // parse to a date
    Date date = formatter.parse(s);
    // get epoch millis
    long millis = date.getTime();
    System.out.println(millis); // 1500475350423
    

    日期格式 使用系统的默认时区,因此上面的最终值( 1500475350423 )将等于我的系统时区中的特定日期和时间(可能与您的不同-仅供记录,我的系统默认时区为 America/Sao_Paulo ). 如果要指定该日期的时区,则需要在格式化程序中进行设置(在调用之前 parse

    // set a timezone to the formatter (using UTC as example)
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    

    有了这个,结果 millis 1500464550423

    若要执行相反的操作(从毫秒值创建日期),必须创建一个 日期

    // create date from millis
    Date date = new Date(1500464550423L);
    // use correct format ('S' for milliseconds)
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:SSS");
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    // format date
    String formatted = formatter.format(date);
    

    Java新日期/时间API

    旧阶级( 日期 , Calendar lots of problems design issues ,它们正被新的API所取代。

    Java 8 ,考虑使用 new java.time API .这更容易, less bugged and less error-prone than the old APIs

    如果您正在使用 Java<=7. ThreeTen Backport ,是Java 8新的日期/时间类的一个很好的后台端口。对于 ThreeTenABP (更多关于如何使用它的信息 here ).

    下面的代码适用于这两种情况。 java.time org.threeten.bp ),但类和方法 姓名 都是一样的。

    作为输入 没有时区信息(只有日期和时间),首先我将其解析为 LocalDateTime (表示没有时区的日期和时间的类)。然后我将这个日期/时间转换为一个特定的时区,并从中获得毫秒值:

    // input string
    String s = "2017.07.19 11:42:30:423";
    // use correct format ('S' for milliseconds)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
    // as the input string has no timezone information, parse it to a LocalDateTime
    LocalDateTime dt = LocalDateTime.parse(s, formatter);
    
    // convert the LocalDateTime to a timezone
    ZonedDateTime zdt = dt.atZone(ZoneId.of("Europe/London"));
    // get the millis value
    long millis = zdt.toInstant().toEpochMilli(); // 1500460950423
    

    1500460950423 ,相当于伦敦时区中的指定日期和时间。

    IANA timezones names (始终采用格式 Region/City 喜欢 美国/圣保罗 Europe/Berlin ). 避免使用三字母缩写(如 CST PST )因为他们是 ambiguous and not standard .

    ZoneId.getAvailableZoneIds() .

    您也可以使用 ZoneOffset.UTC

    相反,您可以获取毫秒值来创建一个瞬间,将其转换为时区并将其传递给格式化程序:

    // create Instant from millis value 
    Instant instant = Instant.ofEpochMilli(1500460950423L);
    // use correct format ('S' for milliseconds)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss:SSS");
    // convert to timezone
    ZonedDateTime z = instant.atZone(ZoneId.of("Europe/London"));
    // format
    String formatted = z.format(formatter);
    
        3
  •  1
  •   ΦXocę 웃 Пepeúpa ツ    7 年前

    第一个建议是转向Java8Java。时间API,而不是学习破碎的java。API日期

    Instant i = Instant.now();
    System.out.println(i.toEpochMilli());
    

    在您的情况下,您可以:

    LocalDateTime myldt = LocalDateTime.parse("2017-06-14 14:29:04",
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    System.out.println(myldt.toInstant(ZoneOffset.UTC).toEpochMilli());
    

    请注意,只要你更多地使用api,你就会找到更多的方法来实现同样的事情,最后你就会停止调用 toEpochMilli

        4
  •  1
  •   Vilius    7 年前
        String strDate = "Jun 13 2003 23:11:52.454 UTC";
        DateTimeFormatter dtf  = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss.SSS zzz");
        ZonedDateTime     zdt  = ZonedDateTime.parse(strDate,dtf);        
        System.out.println(zdt.toInstant().toEpochMilli());  // 1055545912454  
    
        5
  •  1
  •   assembler    7 年前

    你可以试试

    long time = System.currentTimeMillis();
    
        6
  •  1
  •   glytching    7 年前

    如果你有 java.util.Date getTime() 将返回自纪元以来的毫秒数。例如:

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss:sss");
    
    Date dateToBeFormatted = new Date();
    
    // this will print a datetime literal on the above format
    System.out.println(formatter.format(dateToBeFormatted));
    
    // this will print the number of millis since the Java epoch
    System.out.println(dateToBeFormatted.getTime());
    

    这里的关键点是,为了获得自新纪元以来的毫秒数,您不需要 SimpleDateFormatter 因为自纪元以来的毫秒数是 Date