Java 将1小时添加到13位时间戳
我尝试了下面的代码Java 将1小时添加到13位时间戳,java,collections,timestamp,Java,Collections,Timestamp,我尝试了下面的代码 Timestamp timestampDate = scheduled.getInterviewDateAndTime(); //from DB Map<String, Object> map = new HashMap(); map.put("eventTitle", "interview with"); map.put("startDateTime", timestampDate); System.out.println("startDateTime
Timestamp timestampDate = scheduled.getInterviewDateAndTime(); //from DB
Map<String, Object> map = new HashMap();
map.put("eventTitle", "interview with");
map.put("startDateTime", timestampDate);
System.out.println("startDateTime : " + timestampDate);
long addTime = 1*60*60*1000;
timestampDate.setTime(timestampDate.getTime() + TimeUnit.HOURS.toMillis(addTime));
map.put("endDateTime", timestampDate);
System.out.println("endDateTime : " + timestampDate);
如何获得正确的输出?这里有几个问题:
(我假设它就是这样)是一个可变类,因此在它上面设置时间会更改时间戳状态。即使println语句不明显,事后调试映射也会在心跳中显示出来java.sql.Timestamp
- 你计算小时数的逻辑是错误的(你在那里乘了两倍)
- 第一次使用
变量时addTime
- 第二次使用
TimeUnit.toMillis()
java.time.Instant
对象(或ThreeTen的等效版本)的能力,然后是一个工厂构造函数,它将获取Instant
并从中生成Timestamp
(这是java 8版本,ThreeTen将在其他类中具有类似的工厂,而不是在时间戳上)。与来自JDK的旧datetime/calendar类相比,它还利用了java.time
中添加的更干净的时间计算逻辑
第二种变体大致相同,没有使用所有的花哨内容,但因此(对我来说)可读性也差得多:
正如您所看到的,第二个变量几乎就是您所拥有的,但没有不必要的计算
请不要手动计算这些值;我们都知道,一小时应该是60分钟,一分钟是60秒,等等,但是到处读这篇文章很快就会让眼睛模糊。您自己也看到了,首先手动计算,然后仍然使用时间单位1。当你需要增加一天的时候,情况就更糟了,因为考虑到夏令时和历史时区的变化,millis不允许你只增加一天,而不在某个特定时间点提取大量关于一天长度的信息。不是每分钟都是60秒,你知道,也有一些补偿措施。我给你的建议是停止使用过时的时间戳类。如果可以的话,要么完全使用,要么至少尽量减少使用。我将向您展示这两个选项的代码。和他一起工作要好得多。更重要的是,当涉及到时间算术时,比如在约会时间上加一个小时
java.time
更改getInterviewDateAndTime()
以返回即时消息Instant
是来自java.time
的类,它自然地取代了旧的Timestamp
类。同时更改地图的接收器
以接受包含即时
对象的地图。JDBC、JPA等的现代版本很乐意从数据库中检索Instant
对象,并将Instant
存储回数据库中
Instant instantStart = scheduled.getInterviewDateAndTime(); //from DB
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", instantStart);
System.out.println("startDateTime : " + instantStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
map.put("endDateTime", instantEnd);
System.out.println("endDateTime : " + instantEnd);
时间以UTC为单位
编辑:正如Basil Bourque在一篇评论中指出的,增加一小时也可以这样做:
Instant instantEnd = instantStart.plus(Duration.ofHours(1));
结果是一样的
与遗留API一起使用
假设您无法更改getInterviewDateAndTime()
的返回类型和/或地图的接收者绝对需要Timestamp
对象。实现这种限制的标准方法是在自己的代码中仍然使用现代API。一旦收到时间戳
,就将其转换为即时
。当您需要将时间戳
传递给遗留代码时,您只能在最后一刻转换即时
Timestamp timestampStart = scheduled.getInterviewDateAndTime(); //from DB
Instant instantStart = timestampStart.toInstant();
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", timestampStart);
System.out.println("startDateTime : " + timestampStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
Timestamp timestampEnd = Timestamp.from(instantEnd);
map.put("endDateTime", timestampEnd);
System.out.println("endDateTime : " + timestampEnd);
时间与上面相同,但在我的本地时区,因为Timestamp.toString()
以这种方式呈现时间(这让很多人感到困惑)
问题:我可以在Java版本中使用现代API吗?
如果至少使用Java6,则可以
- 在Java8和更高版本中,新的API是内置的
- 在Java6和7GET中,新类的后端口(Three-Ten for)。
Timestamp
和Instant
之间的转换稍有不同,需要通过名为DateTimeUtils
的类进行转换,但并不复杂。其余的都一样
- 在Android上,使用Android版的ThreeTen Backport。它叫ThreeTenABP,我认为这里面有一个很好的解释
请按ctr+k
设置代码格式。是否正确-您检查了吗?该地图的定义是什么?为什么你先输入
,然后再输入
?(第一行很奇怪)map.put(“startDateTime”,timestadeDate);和map.put(“endDateTime”,timestadate);正在引用同一对象。你需要为endDateTime创建一个新对象。想知道你是否有可能摆脱过时的Timestamp
类?现代的Java日期和时间API非常好用。Instant
类是Timestamp
的自然替代品。即使您被绑定到时间戳
,您仍将受益于使用即时
计算“时间戳加1小时”。感谢您的回答。此答案是正确的。从数据库中提取java.time.Instant
对象,而不是过时的java.sql.Timestamp
对象。增加一小时的另一种方法是使用Duration
classmyResultSet.getObject(…,Instant.class).plus(Duration.ofHours(1))
@BasilBourque,虽然我们通常应该避免在新代码中使用Timestamp
,但OP代码可能在已发布的遗留API上下文中工作,迁移到java.time
类可能是不可能的。
Instant instantStart = scheduled.getInterviewDateAndTime(); //from DB
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", instantStart);
System.out.println("startDateTime : " + instantStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
map.put("endDateTime", instantEnd);
System.out.println("endDateTime : " + instantEnd);
startDateTime : 2017-11-29T09:15:00Z
endDateTime : 2017-11-29T10:15:00Z
Instant instantEnd = instantStart.plus(Duration.ofHours(1));
Timestamp timestampStart = scheduled.getInterviewDateAndTime(); //from DB
Instant instantStart = timestampStart.toInstant();
Map<String, Object> map = new HashMap<>();
map.put("eventTitle", "interview with");
map.put("startDateTime", timestampStart);
System.out.println("startDateTime : " + timestampStart);
Instant instantEnd = instantStart.plus(1, ChronoUnit.HOURS);
Timestamp timestampEnd = Timestamp.from(instantEnd);
map.put("endDateTime", timestampEnd);
System.out.println("endDateTime : " + timestampEnd);
startDateTime : 2017-11-29 10:15:00.0
endDateTime : 2017-11-29 11:15:00.0