[英]Why does SimpleDateFormat.parse().getTime() return an incorrect (negative) value?
我有一個String類型的時間戳,我試圖將它轉換為double(並在幾秒鍾內找到結果),這就是我所做的:
double mytimeStamp = 0;
String timeStamp = new SimpleDateFormat(" mm ss S").format(new Date( ));
SimpleDateFormat dateFormat = new SimpleDateFormat(" mm ss S");
try {
mytimeStamp = ((double)dateFormat.parse(timeStamp).getTime())/1000;
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("timeStamp is: "+ mytimeStamp);
問題是我獲得了-2722.515
這樣的值,我不知道為什么。
它為什么是否定的?
代碼有問題嗎?
當我將此時間戳轉換為mm ss S
與實際時間不匹配,這似乎是另一個問題!
這是一個時區差異問題。
由於您只指定了分鍾和秒,因此日期將在1 Jan 1970 00:mm:ss
年1 Jan 1970 00:mm:ss
( mm
和ss
是當前時間的分鍾和秒)。
我將你的例子簡化為:
String timeStamp = "00 00 00";
SimpleDateFormat dateFormat = new SimpleDateFormat("HH mm ss");
double hour = dateFormat.parse(timeStamp).getTime()/1000.0/60/60;
System.out.println("hour is: "+ hour);
打印出來的小時應該是GMT
與當地時區的偏差。
原因是:
SimpleDateFormat
是區域設置敏感的,因此dateFormat.parse(timeStamp)
將返回為給定時區創建Date
對象(默認為本地時區)。 然后getTime()
從midnight 1 Jan 1970 **GMT**
獲得毫秒數midnight 1 Jan 1970 **GMT**
。 因此,該值將被當地時區距GMT
時間的距離所抵消。
如何解決:
您可以通過在調用parse
之前設置dateFormat
對象的時區來修復它,如下所示:
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
---實際上有更好的方法可以做到這一點,但是如果你想使用日期,請跳到編輯前的答案---
日期實際上並不是你想要的,這似乎是在實際需要從現實世界日歷中挑選時間之外的時間計算。
你最好自己編寫自己的課程,以避免日期必須做的所有令人討厭的特殊處理,以便跟上格里高利歷。 這種特殊處理包括(但不限於)時區感知,夏令時,宣布的“跳過天數”,閏秒,閏年等。
public TimeOnly {
private long timestamp;
private int millis;
private int seconds;
... etc ...
public TimeOnly(int hours, int minutes, int seconds, int millis) {
this.timestamp = millis + seconds * 1000L + minutes * 60000L + hours * 3600000L;
this.millis = millis;
this.seconds = seconds;
... etc ...
}
private TimeOnly(long timestamp) {
this.timestamp = timestamp;
this.millis = timestamp % 1000;
this.seconds = timestamp % 60000L - this.millis;
... etc ...
}
public long getTimestamp() {
return timestamp;
}
public int getMillis() {
return millis;
}
public int getSeconds() {
return seconds;
}
... etc ...
}
public TimeFormatter {
public TimeFormatter() {
}
public String format(Time time) {
StringBuilder builder = new StringBuilder();
builder.append(String.valueOf(time.getHours()));
builder.append(":");
builder.append(String.valueOf(time.getMinutes()));
builder.append(":");
builder.append(String.valueOf(time.getSeconds()));
builder.append(".");
if (time.getMillis() < 10) {
builder.append("00");
} else if (time.getMillis() < 100) {
builder.append("0");
}
builder.append(time.getMillis());
return builder.toString();
}
這個解決方案似乎正在重新發明輪子,但實際上它避免使用八角形作為輪子。 日期的行為似乎不是您想要的,盡管您可以使Date適用於某些有限范圍的值。
如果你想得到真正的幻想,你可以使上述工具可比,等等。但是,我會建議反對的事情。 在構造之后不要提供更新方法,因為這會強制進行一些非常討厭的重新計算並使代碼更難維護。 而是提供返回新TimeOnlys的方法,以響應您希望實現的操作。
public TimeOnly addSeconds(int value) {
int stamp = this.timestamp;
stamp += value * 60000L;
if (stamp < timestamp) {
throw new Excepton("overflow");
}
return new TimeOnly(stamp);
}
另外,不要實現你不會使用的東西。 未使用的代碼往往是錯誤的肥沃土壤。
當然,股票回答所有“時間”的事情,考慮使用JodaTime,它區分所有不同類型的時間測量。 然而,對於像這樣的小問題,它類似於使用坦克殺死螞蟻。
---編輯前的答案---
如果沒有完整的時間規范(年,月,日,小時,分鍾,秒,毫秒),則在第一步中格式化的時間值將包含許多未指定的字段。 這些領域的內容很可能是垃圾。
然后getTime()
作用於整個Date
對象,將有效字段和垃圾轉換為值,其中垃圾甚至可以修改有效值(96秒= 1分36秒,因為字段交互)。
解決這個問題的最佳方法是將所有“僅限時間”的日期初始化為一個已知的日期,因此當您進行比較和數學運算時(是, 3 11 23
> 1 02 10
?),您會獲得一致的結果(是的, 3 11 23
> 1 02 10
,因為它實際上是2013 02 10 00 03 11 23
> 2013 02 10 00 03 11 23
而不是2013 02 10 00 03 11 23
與2000 02 10 00 03 11 23
選擇使用日期時,請避開2月29日附近的天數,接近夏令時的天數等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.