使用存储历史对象时区信息的系统如下:
o1: dt= 2022-07-15 13:32:00 offset=5 dst=false
o2: dt= 2022-01-15 13:32:00 offset=5 dst=true
o3: dt= 2022-07-15 13:32:00 offset=7 dst=false 如果把“美国/纽约”这样的时区储存起来,生活会容易得多,但这正是我必须面对的。我的最终目标是将这些历史日期与当前时间进行比较,并得到它们之间的时间差。
创建当前时间很容易。我可以在UTC买到
ZonedDateTime.now(ZoneId.of("UTC"))
2022-07-15T15:33:04.177Z[UTC]或者我的本地时区
ZonedDateTime.now()
2022-07-15T11:33:28.648-04:00[America/New_York]问题是,如何将表数据读入ZonedDateTime进行苹果与苹果的比较。例如,一些神奇的方法,比如
ZonedDateTime.fromOffset(5).fromDst(false).asTz('UTC')
发布于 2022-07-15 16:26:19
您可以在指定的偏移量中使用ZoneOffset,DST /false在这里似乎不相关。假设时间戳是本地的(而不是UTC),您可以这样做:
public static void main(String[] args) {
record TimestampAndOffset(String timestamp, int offsetHours) { }
var timeData = List.of(
new TimestampAndOffset("2022-07-15T13:32:00", 5),
new TimestampAndOffset("2022-01-15T13:32:00", 5),
new TimestampAndOffset("2022-07-15T13:32:00", 7));
timeData.forEach(to -> {
LocalDateTime localTimestamp = LocalDateTime.parse(to.timestamp());
var zoneOffset = ZoneOffset.ofHours(to.offsetHours());
var zonedValue = ZonedDateTime.of(localTimestamp, zoneOffset);
System.out.println(zonedValue);
System.out.println(zonedValue.withZoneSameInstant(ZoneOffset.UTC));
});
}为了简化本例的解析,我使用了以T为分隔符的ISO-8601格式。
输出:
2022-07-15T13:32+05:00
2022-07-15T08:32Z
2022-01-15T13:32+05:00
2022-01-15T08:32Z
2022-07-15T13:32+07:00
2022-07-15T06:32Z正如user16320675在评论中指出的那样,重要的警告是,重复检查您的偏移量的含义,因为根据您问题的原版,您的数据可能使用逆偏移量(例如5而不是-5),在这种情况下,您需要使用ZoneOffset.ofHours(-to.offsetHours())代替。
正如Bourque在注释中提到的,请考虑使用OffsetDateTime是否对您的用例更有意义。
发布于 2022-07-15 22:19:30
@马克·罗特韦尔回答了这个问题。我不得不稍微修改他的答案,以适应我的确切需求和在Java 8上的限制,所以我现在发布我的确切解决方案,以防有用。
LocalDateTime localDt = LocalDateTime.parse("2022-07-15T13:32:00");
// IF DST MAKE THIS 4
ZoneOffset offset = ZoneOffset.ofHours(-5);
OffsetDateTime offsetDt = localDt.atOffset(offset);
// Not sure the canonical way to do a duration check but this seems to work
// Duration d = Duration.between( offsetDt , Instant.now());
Instant now = Instant.now();
boolean isFutureDate = offsetDt.toInstant().getEpochSecond() > now.getEpochSecond();
log.info("Original: {}, OffsetDt:{}, Now: {}, isFutureDate: {}" , localDt, offsetDt, now, isFutureDate);哪种输出
Original: 2022-07-15T13:32, OffsetDt:2022-07-15T13:32-05:00, Now: 2022-07-18T16:28:48.384Z, isFutureDate: false发布于 2022-07-16 01:02:12
tl;dr
你说过:
我的最终目标是将这些历史日期与当前时间进行比较,并得到它们之间的时间差。
record History( String dt , int offset , boolean dst ) { }
Instant now = Instant.now();
List.of(
new History( "2022-07-15 13:32:00" , 5 , false ) ,
new History( "2022-01-15 13:32:00" , 5 , true ) ,
new History( "2022-07-15 13:32:00" , 7 , false )
)
.forEach(
history -> System.out.println(
Duration.between(
LocalDateTime
.parse(
history.dt().replace( " " , "T" )
)
.atOffset(
ZoneOffset.ofHours( history.offset() )
)
.toInstant() ,
now
)
)
);PT17H4M40.423919S PT4361H4M40.423919S PT19H4M40.423919S
OffsetDateTime
另外两个答案-- 马克·罗特韦尔和亚当·休斯 --基本上都是正确的。但是,就像问题一样,他们使用的是ZonedDateTime,而不是更合适的类OffsetDateTime。而且它们没有解决问题中提出的具体解析需求。显然,输入数据已经存在于对象中,所以我将将其表示为记录。
public record History( String dt , int offset , boolean dst ) { }填充一些数据。
List < History > historyList =
List.of(
new History( "2022-07-15 13:32:00" , 5 , false ) ,
new History( "2022-01-15 13:32:00" , 5 , true ) ,
new History( "2022-07-15 13:32:00" , 7 , false )
);我们需要为每个输入生成一个java.time.OffsetDateTime对象。我们可以向记录中添加一个方法来执行该工作。
要解析给定的输入,我们可以定义一个格式模式匹配的DateTimeFormatter,也可以执行字符串操作,使输入符合OffsetDateTime.parse中默认使用的ISO 8601标准格式。我选择后者。我们只需要用一个T替换中间的空间。
正如罗特韦尔在他的回答中提到的那样,夏时制(DST)是否有效的布尔值与此无关。我们忽略History记录中的成员字段。
public record History( String dt , int offset , boolean dst )
{
OffsetDateTime toOffsetDateTime ( )
{
LocalDateTime ldt = LocalDateTime.parse( this.dt.replace( " " , "T" ) );
ZoneOffset o = ZoneOffset.ofHours( this.offset );
OffsetDateTime odt = ldt.atOffset( o );
return odt;
}
}捕捉当前的时刻。
Instant now = Instant.now() ;您的目标是确定经过的时间。为此请使用Duration。为此,我们可以向History记录添加另一个方法。
package work.basil.example.history;
import java.time.*;
public record History( String dt , int offset , boolean dst )
{
OffsetDateTime toOffsetDateTime ( )
{
LocalDateTime ldt = LocalDateTime.parse( this.dt.replace( " " , "T" ) );
ZoneOffset o = ZoneOffset.ofHours( this.offset );
OffsetDateTime odt = ldt.atOffset( o );
return odt;
}
Duration elapsed ( final Instant instant )
{
Duration d = Duration.between( this.toOffsetDateTime().toInstant() , instant );
return d;
}
}循环输入以报告它们经过的时间。
Instant now = Instant.now();
for ( History history : historyList )
{
String message = history.elapsed( now ).toString() + " from " + history.toString() + " to " + now.toString();
System.out.println( message );
}跑的时候。
PT16H27M40.119075S from History[dt=2022-07-15 13:32:00, offset=5, dst=false] to 2022-07-16T00:59:40.119075Z
PT4360H27M40.119075S from History[dt=2022-01-15 13:32:00, offset=5, dst=true] to 2022-07-16T00:59:40.119075Z
PT18H27M40.119075S from History[dt=2022-07-15 13:32:00, offset=7, dst=false] to 2022-07-16T00:59:40.119075Zhttps://stackoverflow.com/questions/72996432
复制相似问题