簡體   English   中英

SimpleDateFormat在Android中表現得很奇怪

[英]SimpleDateFormat is behaving strange in Android

以下是我用來獲取當天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 ,目前處於夏令時(DST),對於-07:00 (比UTC晚7個小時) 的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價值:1462431600000 | 時刻1:2016-05-05T23:55:40.907Z | 時刻2:2016-05-05T07:00:00Z

工作太辛苦了

你的問題令人困惑,但似乎你正試圖抓住當天的第一時刻。 你是以錯誤的方式去做,而且工作太辛苦了。

時區

您的代碼似乎與java.util.Date類一起使用。 該類代表UTC時間軸上的一個時刻。

但是你沒有得到UTC當天的第一時刻。 解析該僅日期字符串以生成新的java.util.Date (日期加上時間值,盡管名稱有誤導性)時,將隱式應用JVM的當前默認時區。 將時區無形地注入到流程中非常困惑。

相反,你應該有意識地考慮時區,並始終明確時區是你的編碼(如下所示)。

java.time

事實證明,舊的java.util.Date / .Calendar類設計糟糕,令人困惑且麻煩。 它們現在是遺留的,取而代之的是Java 8及更高版本中內置的java.time框架。 許多java.time功能都被反向移植到Java 6和7,進一步適用於Android

對於沒有時間且沒有時區的僅日期值,請使用LocalDate類。 雖然不存儲時區,但確定諸如“今天”之類的日期需要時區。 如果省略,則應用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 );

我強烈建議不要使用處理日期時間值作為從紀元開始的計數。 這就像使用Unicode代碼點的數組而不是使用與String相關的類來處理文本。 但如果你堅持,你可以轉換。 但請注意數據丟失,因為java.time類具有更精細的納秒分辨率,而您要求的是毫秒(這是避免將日期時間作為從紀元開始計數的許多原因之一)。 首先在UTC的時間軸上提取一個Instant ,一個分辨率為納秒的時刻。

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 );

但這可能不是最合適的路線。 時區是與UTC偏移量 加上一組針對夏令時(DST)等異常的規則。 根據定義,UTC沒有這樣的異常。 因此更合適的是OffsetDateTime而不是ZonedDateTime

OffsetTime ot = OffsetTime.of( 0 , 0 , 0 , 0 , ZoneOffset.UTC );
OffsetDateTime odt = today.atTime( ot );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM