我有一个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
与实时不符时,这似乎是另一个问题!
答案 0 :(得分:13)
这是一个时区差异问题。
由于您只指定了分钟和秒,因此日期将显示在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**
获得毫秒数。因此,该值将被本地时区距GMT
的距离所抵消。
如何修复:
您可以通过在调用dateFormat
之前设置parse
对象的时区来解决此问题:
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
答案 1 :(得分:1)
---实际上有更好的方法可以做到这一点,但是如果你想使用日期,请跳到编辑前的答案---
日期实际上并没有做你想要的事情,这似乎是在实际需要选择真实世界日历的时间之外的时间计算。
你最好写自己的班级,以避免日期必须做的所有讨厌的特殊处理,以跟上格里高利历。这种特殊处理包括(但不限于)时区感知,夏令时,宣布的“跳过天数”,闰秒,闰年等。
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
&gt; 1 02 10
? )您得到一致的结果(是的,3 11 23
&gt; 1 02 10
,因为与{{1}相比,它实际上是2013 02 10 00 03 11 23
&gt; 2013 02 10 00 03 11 23
而不是2013 02 10 00 03 11 23
}
选择使用日期时,请避开2月29日附近的天数,接近夏令时班次的天数等。