2017-04-13 86 views
0

我有兩個日期對象Date1和Date2。日期1有一個時間和date2有時間,與UTC標準(只有時間內,而不是實際日期本身):比較時間偏移量使用兩個日期對象

Date1: Thu Apr 13 20:41:46 CDT 2017

Date2: Thu Apr 13 15:41:46 CDT 2017

我想借這兩個日期,提取它們的時間,比較它們,然後確保它們與我的系統時間和UTC正確偏移(此比較還需要考慮夏令時)。

請注意,沒有辦法,我可以用java.time作爲輸入,我的理解會容易得多,但與我們的配置我使用java.util.Date作爲輸入日期卡住

這裏是我的代碼來產生這些日期值,我只需要一種方法來驗證兩者之間的差異實際上是正確的偏移量(沒有硬編碼的偏移量,不得不改變它在每個夏令時的變化):

public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS"; 
public static final int MILLI_TO_HOUR = 1000 * 60 * 60; 

public static void main(String args[]) throws java.text.ParseException { 
    Date date1 = nowInUTC(); 
    Date date2 = Date.from(Instant.now()); 
    System.out.println("date1: " + date1); 
    System.out.println("date2: " + date2); 

    /* Needs to be modified to contain the logic 
     * I need to verify that the time given in date2 is the offset from date1 
     * in respect to its timezone. You can ignore the CDT in date1*/ 
    if(true){ 
     System.out.println("You have the correct offset!"); 
    } 
    else 
    { 
     System.out.println("you do not have the correct offset!"); 
    } 
} 

private static long toHours(long millis){ 
    return millis/MILLI_TO_HOUR; 
} 

private static Date nowInUTC() { 
    try { 
     Date date = new Date(new SimpleDateFormat(TIMESTAMP_FORMAT).parse(
       nowInUTCAsString()).getTime()); 
     return date; 
    } 
    catch(ParseException pe){ 
     pe.printStackTrace(); 
     return null; 
    } 
} 

private static String nowInUTCAsString() { 
    SimpleDateFormat sdf = new SimpleDateFormat(TIMESTAMP_FORMAT); 
    sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 
    return sdf.format(new Date()); 
} 
+0

你在問什麼,沒有任何意義(事實上可以幫助你)。一個'Date'對象*沒有偏移到UTC *。這是一個常見的誤解,可能很大程度上得益於它的'toString'方法獲取JVM的時區設置並根據它打印日期。所以在你的程序中有兩個'Date'對象,其中沒有一個可以有偏移量,並且兩者都將以相同的偏移量打印,即JVM的偏移量。 –

+0

我注意到你正在使用'Instant.now()',其中'Instant'是'java.time'類(我假設)。你是說你的輸入必須是一個'java.util.Date',所以你可以將它轉換爲一個'java.time'類,並使用新的類來處理?如果是這樣,這是我會建議。 –

+0

你的'nowInUTC()'做了一件我無法相信你想要的事情。中央夏令時與UTC的偏差爲-5小時。所以當你在15:41:46 CDT運行你的代碼時,UTC時間是20:41:46,而'nowInUTCAsString()'正確產生了一個像'2017-04-13T20:41:46.357'這樣的字符串(只是猜測小數點)。然後'nowInUTC()'在*你的本地時區*中解析這個字符串,產生一個等於20:41:46 CDT的Date,這與UTC的1:41:46相同。由於日期始終顯示在JVM的時區中,因此您將其視爲屏幕上的「Thu Apr 13 20:41:46 CDT 2017」。 –

回答

1

感謝您的意見,澄清您的有趣的challe NGE。我知道你需要提前5個小時製作一個日期,以彌補數據庫採用CDT時間並將其理解爲UTC。實際偏移量取決於您計算機的時區設置。我假設你的數據庫在本地運行,或者至少保證與你的JVM具有相同的時區設置 - 這是你應該檢查的假設。

您的代碼基本上是正確的,生成兩個日期的差異等於您的計算機與UTC的偏移量,所以您不應該真的需要驗證該事實。我將在下面的聲明中增加一兩個細微差別。

首先,您如何驗證?接受你的話,你想。這裏是我的建議:

LocalDateTime date1AsLdt = date1.toInstant() 
      .atZone(ZoneId.systemDefault()) 
      .toLocalDateTime(); 
    LocalDateTime utc = OffsetDateTime.now(ZoneOffset.UTC).toLocalDateTime(); 
    if (date1AsLdt.isEqual(utc)){ 
     System.out.println("You have the correct offset!"); 
    } 
    else 
    { 
     System.out.println("you do not have the correct offset!"); 
    } 

即使我聲稱這是檢查的正確方式,爲您的生產date1的方式是正確的,我的舊電腦就可以打印you do not have the correct offset!這是因爲這兩個時間相差高達幾百毫秒。這不是錯誤,而是代碼中的錯誤。它來自您的代碼讀取系統時鐘兩次,根據兩次讀數之間的時間差異,它們可能會或可能不會達成一致。您首先創建new Date(),然後再通過Instant.now()讀取時鐘。我建議你只讀一次,並在兩個日期使用相同的讀數。

由於您在代碼中使用了java.time.Instant,我認爲只要您最終生成java.util.Date,就可以在內部使用java.time。我上面的代碼中的LocalDateTime也在java.time

如果這是好的,在你的代碼中不需要轉換爲字符串和返回的複雜性。我建議:

private static Date nowInUTC() { 
    LocalDateTime utc = OffsetDateTime.now(ZoneOffset.UTC).toLocalDateTime(); 
    return Date.from(utc.atZone(ZoneId.systemDefault()).toInstant()); 
} 

正如我所說的,上面有很多假設。如果我在某個地方錯了,請回復,我很樂意再看一次。

最後的警告。從DST到每個秋季的標準時間都有幾個小時的時間,其中時鐘時間不明確。即使你的程序正確地產生了UTC時間(這從來就不會像UTC那樣含糊不清),你的數據庫將需要選擇傳遞給它的時間的解釋,而我看不到它可以採用正確的方法。