java - SimpleDateFormat 在 Android 中的行为很奇怪

标签 java android date simpledateformat

以下是我用来获取当天 00 小时的代码(长格式)。

我在android中运行下面的代码。

该方法在大多数情况下正确返回值。但有时它会返回 的值System.currentTimeMillis() .

import java.text.SimpleDateFormat;
import java.util.Date;
public static final SimpleDateFormat SD_FORMAT_DAY_MONTH_YEAR = new SimpleDateFormat("dd/MM/yyyy");


public static long getLongForCurrent00hr() {
    Date date = new Date();
    String time = SD_FORMAT_DAY_MONTH_YEAR.format(date);

    long value;
    try {
        Date date2 = SD_FORMAT_DAY_MONTH_YEAR .parse(time);
        value = date2.getTime();
    } catch (ParseException e) {
        value = 0;
    }
    return value;
}

为什么返回 System.currentTimeMillis() ?
我该如何解决这个问题?

我更感兴趣的是知道为什么..

当我今天运行这段代码时,我通过输入日志来检查它:

大多数时候它会返回:1462386600000

还有几次 System.currentTimeMillis() 像 1462430867302。

最佳答案

您的示例代码有效

当您构建它时,我认为您的代码没有问题(请阅读下面的批评)。

此处几乎显示了您的确切代码。两个变化:

  • 我将您的格式常量设为局部变量。 (只是为了让这个演示更简单,一段代码可以复制粘贴)
  • 我添加了几个电话以获得 Instant UTC 中的当前时刻.类似于 java.util.Date , 但是 Instant::toString创建一个显示 UTC 的字符串,而不是混淆地应用 JVM 的当前时区。因此,您可以更清楚地看到您确实获得了 JVM 当前默认时区的第一时刻。在我运行此代码的情况下,我的 JVM 当前的默认时区是 America/Los_Angeles , 当前为 offset-from-UTC 的夏令时 (DST)对于 -07:00 (比 UTC 晚七个小时)。

  • 示例代码。
    Date date1 = new Date ();
    SimpleDateFormat SD_FORMAT_DAY_MONTH_YEAR = new SimpleDateFormat ( "dd/MM/yyyy" );
    String time = SD_FORMAT_DAY_MONTH_YEAR.format ( date1 );
    
    Date date2 = null;
    long value;
    try {
        date2 = SD_FORMAT_DAY_MONTH_YEAR.parse ( time );
        value = date2.getTime ();
    } catch ( ParseException e ) {
        value = 0;
    }
    System.out.println ( "date1: " + date1 + " date2: " + date2 + " value: " + value + " | instant 1: " + date1.toInstant () + " | instant 2: " + date2.toInstant () );
    

    跑的时候。

    date1: Thu May 05 16:55:40 PDT 2016 date2: Thu May 05 00:00:00 PDT 2016 value: 1462431600000 | instant 1: 2016-05-05T23:55:40.907Z | instant 2: 2016-05-05T07:00:00Z



    工作太辛苦

    您的问题令人困惑,但似乎您正试图捕捉一天的第一刻。你走错路了,工作太努力了。

    时区

    您的代码似乎正在使用 java.util.Date类(class)。该类代表 UTC 时间线上的一个时刻。

    但是您没有在 UTC 中获得一天中的第一刻。当您解析该仅日期字符串以生成新的 java.util.Date (日期加时间值,尽管名称具有误导性),JVM 的当前默认时区是隐式应用的。将时区无形地注入(inject)到流程中非常令人困惑。

    相反,您应该有意识地考虑时区,并且始终明确时区是您的编码(如下所示)。

    java.time

    java.util.Date/.Calendar类已被证明设计不佳、令人困惑和麻烦。它们现在是遗留的,被 java.time 取代。 Java 8 及更高版本中内置的框架。 java.time 的大部分功能是back-ported to Java 6 & 7further adapted for Android .

    对于没有时间和时区的仅日期值,请使用 LocalDate 类(class)。虽然不存储时区,但确定诸如“今天”之类的日期需要时区。如果省略,则应用 JVM 当前的默认时区(请注意,该默认值可能会在运行时随时更改)。
    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    LocalDate today = LocalDate.now( zoneId );
    

    你似乎想要一天的第一刻。不要假设那一刻的时间是00:00:00.0 .虽然通常是正确的,但在某些时区,诸如夏令时之类的异常情况可能会转移到另一个时间。让 java.time 确定正确的时间。调用 [ atStartOfDay][2]生成 ZonedDateTime 适合指定时区的第一刻。
    ZonedDateTime zdt = today.atStartOfDay( zoneId );
    

    我强烈建议不要使用处理日期时间值作为计数-epoch .这就像使用 Unicode 代码点的整数数组,而不是使用与字符串相关的类来处理文本。但如果你坚持,你可以转换。但要注意数据丢失,因为 java.time 类具有更精细的纳秒分辨率,而您要求的是毫秒(避免将日期时间处理为从纪元开始计数的众多原因之一)。首先提取一个Instant ,UTC时间轴上的时刻,分辨率为纳秒。
    Instant instant = zdt.toInstant();
    long millisecondsFromEpoch = instant.toEpochMilli(); // WARNING: Possible data loss (going from nanoseconds to milliseconds).
    

    世界标准时间

    如果您确实想要 UTC 的第一刻,那也很容易。

    您可以使用常量 ZoneOffset.UTC 将 UTC 指定为时区。 . (该常量恰好在 ZoneOffset 中,它是 ZoneId 的子类。)
    ZonedDateTime zdt = today.atStartOfDay( ZoneOffset.UTC );
    

    但这可能不是最合适的路线。时区是 offset-from-UTC加上一组异常规则,例如 Daylight Saving Time (DST) .根据定义,UTC 没有此类异常。所以更合适的是 OffsetDateTime 而不是 ZonedDateTime .
    OffsetTime ot = OffsetTime.of( 0 , 0 , 0 , 0 , ZoneOffset.UTC );
    OffsetDateTime odt = today.atTime( ot );
    

    关于java - SimpleDateFormat 在 Android 中的行为很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37044443/

    相关文章:

    java - getDeclaredMethods() 和隐藏的父类(super class)静态方法

    android - android软键盘可以启动其他IME吗

    android - 显示 Activity 后执行 AsyncTask

    android - 在横向和纵向模式之间切换会导致一些 UI 问题

    java.util.Calendar getMaximum 最后一天返回错误

    java - 提供示例数据来测试 JavaFX GUI

    java - TypeParameter 作为表达式参数

    java - 如果与 new 一起使用,intern() 会创建多少个对象?

    javascript - 夏令时与 JavaScript

    date - 对于国际网络应用程序,我应该使用哪种日期格式?