当前位置: 首页 > 面试题库 >

Java 8 java.time:在Instant vs LocalDateTime中添加TemporalUnit

骆昊阳
2023-03-14
问题内容

我正在使用Java 8中的新java.time包。我有一个遗留数据库java.util.Date,可以将其转换为Instant

我想做的是添加一个基于另一个数据库标志的时间段。我可能要加上几天,几周,几个月或几年。我不想关心我要添加的内容,并且希望将来能够添加更多选项。

我的第一个想法是Instant.plus(),但这给了我UnsupportedTemporalTypeException大于一天的价值。即时显然不支持大时间单位上的操作。好吧,随便吧LocalDateTime

因此,我得到了以下代码:

private Date adjustDate(Date myDate, TemporalUnit unit){
    Instant instant = myDate.toInstant();
    LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    dateTime = dateTime.plus(1, unit);
    Instant updatedInstant = dateTime.atZone(ZoneId.systemDefault()).toInstant();
    return new Date(dueInstant.toEpochMilli());
}

现在,这是我第一次使用新的time API,因此我可能在这里错过了一些东西。但是对我来说,我不得不走了:

Date --> Instant --> LocalDateTime --> do stuff--> Instant --> Date.

即使我不必使用Date部分,我仍然认为它有点尴尬。所以我的问题是,我这样做是完全错误的,什么是最好的方法?

编辑 :扩展评论中的讨论。

我想我现在对LocalDateTime和Instant如何与java.util.Date和java.sql.Timestamp一起玩有个更好的主意。感谢大家。

现在,有一个更实际的考虑。假设某个用户向我发送了一个来自世界各地的日期(任意时区)。他们发送给我2014-04-16T13:00:00,我可以将其解析为LocalDateTime。然后,我将其直接转换为java.sql.Timestamp并保存在我的数据库中。

现在,无需执行任何其他操作,就从数据库中提取java.sql.timestamp,转换为LocalDateTimeusing
timestamp.toLocalDateTime()。都好。然后,我使用ISO_DATE_TIME格式将此值返回给用户。结果是2014-04-16T09:00:00

我认为这种差异是由于某种类型的往返于UTC的隐式转换。我认为我的默认时区可能已应用于该值(EDT,UTC-4),这可以解释为什么该数字减少4小时。

新问题。从本地时间到UTC的隐式转换在哪里发生?保存时区的更好方法是什么。我是否应该直接从本地时间(2014-04-16T13:00:00)转到字符串LocalDateTime?我应该从用户输入中期待一个时区吗?


问题答案:

我将继续根据最终解决方案以及很长的评论链的摘要发布答案。

首先,整个转换链如下:

Date --> Instant --> LocalDateTime --> Do stuff --> Instant --> Date

必须保留时区信息,并且仍要对类似Date的对象执行操作,该对象知道Calendar及其中的所有上下文。否则,我们将存在隐式转换为本地时区的风险,如果尝试将其转换为人类可读的日期格式,则时间可能因此而发生了变化。

例如,该类toLocalDateTime()上的方法java.sql.Timestamp隐式转换为默认时区。就我的目的而言,这是不可取的,但不一定是不良行为。但是,重要的是要意识到这一点。这就是直接从旧版Java日期对象转换为LocalDateTime对象的问题。由于传统对象通常被假定为UTC,因此转换使用本地时区偏移量。

现在,假设我们的程序接受的输入2014-04-16T13:00:00并以形式保存到数据库java.sql.Timestamp

//Parse string into local date. LocalDateTime has no timezone component
LocalDateTime time = LocalDateTime.parse("2014-04-16T13:00:00");

//Convert to Instant with no time zone offset
Instant instant = time.atZone(ZoneOffset.ofHours(0)).toInstant();

//Easy conversion from Instant to the java.sql.Timestamp object
Timestamp timestamp = Timestamp.from(instant);

现在我们加上一个时间戳,并增加一些天数:

Timestamp timestamp = ...

//Convert to LocalDateTime. Use no offset for timezone
LocalDateTime time = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));

//Add time. In this case, add one day.
time = time.plus(1, ChronoUnit.DAYS);

//Convert back to instant, again, no time zone offset.
Instant output = time.atZone(ZoneOffset.ofHours(0)).toInstant();

Timestamp savedTimestamp = Timestamp.from(output);

现在,我们只需要输出格式为的可读字符串即可ISO_LOCAL_DATE_TIME

Timestamp timestamp = ....
LocalDateTime time = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneOffset.ofHours(0));
String formatted = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(time);


 类似资料:
  • 问题内容: 我试图在按钮上显示一些文本和图像。我正在从这里使用代码 我可以在正确的位置看到图像,但是文本没有出现。我认为没有用。 问题答案: 我尝试的代码获得了输出U所遇到的问题。 设置背景颜色并检查 Swift3 and handle the action as

  • 我创建了一个表单,其中添加了一个,它有3列。第二列和第三列有编辑器。 我希望当我们选择第二列组合框的第一项时,第三列组合框的第一个组合框也应该被选择,反之亦然。 我该怎么做?

  • 问题内容: 我正在尝试提供一组可以重复或删除的输入。 我发现并使用了以下方法的组合:https : //jsfiddle.net/69z2wepo/36745/ 并且(因为上面的代码无法处理删除操作):https : //codepen.io/lichin-lin/pen/ MKMezg 我可能不需要指向一个特定的输入,因为在我的界面中,您应该始终只添加一个新的(如果之前的一个已填充)(我将在稍后

  • 问题内容: TL; DR:如何在ModelForm中为ForeignKey添加“添加新”按钮? 长版:我在项目中使用Django 1.7。我的models.py中有这两个模型 [省略了一些其他不相关的字段] 我正在使用ModelForm用新命令填充数据库,如下所示: Django在为客户字段添加下拉菜单方面做得很好,并在其中添加了来自客户的条目。不过,我想拥有一个“添加新客户”链接/按钮/以便在添

  • 问题内容: 我是Java的新手,并且遇到在applet面板中添加图像的问题。我的图像在同一文件夹中。我的小程序可见,没有任何问题,但仅不显示图像。 问题答案: 在接受一个构造函数假定字符串表示的路径和文件名。 只有受信任的applet可以访问,然后只能在客户端文件系统(而不是服务器)上访问。如果这是应用程序资源,则应位于服务器上,并且可以通过URL访问。 请注意,构造函数还将接受URL,而不是上面

  • 问题内容: 我的网站顶部菜单中有外部链接。我想在新标签页中打开这些链接。我可以在HTML中使用“ target = _blank”来实现。 是否有类似的CSS属性或其他属性? 问题答案: 抱歉不行。在2013年,无法使用纯CSS做到这一点。 更新 :感谢showdev链接到CSS3 Hyperlinks的过时规范,是的,没有浏览器实现它。因此,答案仍然有效。

  • 问题内容: 如何在jQuery中的特定HTML标签中添加属性? 例如,像下面这样的简单HTML: 然后添加一个属性disable =“ true”,如下所示: 问题答案: 您可以像这样添加属性: 但是,对于和这样的DOM属性,正确的方法(从JQuery 1.6开始)是使用。

  • 我需要在EditText(Oe)中最后写入的数字后添加一个字符“S”,以便: 如果我写i号:“123”,它必须发送“123S”。如果我写“1234”,它必须发送“1234S”。 那要怎么做? 我的代码: