试图将本地时区与设置的时区进行比较



我正在尝试获取机器与美国东海岸的本地时间之间的差异,尽管这不是特定的。

我使用以下内容,但它总是返回UTC的差值,而不是PC设置的时区。

LocalDateTime now = LocalDateTime.now();
ZoneId zone = ZoneId.of("America/New_York");
ZoneOffset zoneOffSet = zone.getRules().getOffset(now);
System.out.println(zoneOffSet + " " + ZonedDateTime.now() + " " + Instant.now());

无论我将电脑时间设置为哪个时区,它都会显示区域偏移的-04:00。

我在这里做错了什么?

LocalDateTime不是瞬间

一般提示:切勿拨打LocalDateTime.now()。我无法想象这样做是正确的。

LocalDateTime类故意缺少任何时区或UTC偏移量的概念。因此LocalDateTime不能代表一个时刻,不能跟踪时间线上的特定点。

确定时区在特定时刻使用的偏移量

我从你的散文中看不出你的目标到底是什么。但查看您的代码,您似乎想知道特定时区的当前UTC偏移量是多少。这很容易。

ZoneId表示一个特定的时区。每个时区都有一个ZoneRules对象,其中包含该区域内人员使用的偏移量的过去、现在和未来变化的历史。

给这些规则传递一个时间(Instant),以请求当时有效的偏移。结果是一个ZoneOffset,一个小时分秒数。

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZoneRules rules = z.getRules() ;
Instant now = Instant.now() ;  // Capture the current moment as seen in UTC (an offset of zero hours-minutes-seconds). 
ZoneOffset offset = rules.getOffset( now ) ;

您可以通过调用ZoneOffset#toString生成标准ISO 8601格式的文本来表示该偏移值。

ZonedDateTime zdt = now.atZone( z ) ;
String message = zdt.toString() + " has an offset of " + offset + "." ;
System.out.println( message ) ;

请在IdeOne.com上实时查看此代码。

2021-10-09T00:36:54.432057-04:00[America/New_York]的偏移量为-04:00。

你说:

无论我将电脑时间设置为什么,它都会显示区域偏移的-04:00。

当然。无论你身在世界何处,纽约地区的人们都会将时钟设置为比UTC晚四小时。计算机上使用的默认时区对该事实没有影响。

如果要将特定时区的偏移量与另一时区的偏移进行比较,请运行与上面所示相同的代码,为相同的Instant获取第二个ZoneOffset。要访问JVM的当前默认时区,请调用ZoneId.systemDefault

您可以通过将每个偏移量转换为总秒数(正或负)来进行比较。致电ZoneOffset#getTotalSeconds

int offsetInSeconds_NewYork = offset.getTotalSeconds() ;
int offsetInSeconds_MyDefaultZone = ZoneId.systemDefault().getRules().getOffset( now ).getTotalSeconds() ;

我取了我发布的内容,并在其中添加了一些内容,以获得我的本地时区,并从纽约的JVM(我的PC时区)中相互减去以获得时区差异,从而获得时区差异。

然后我取了你的代码,并对相同的输出做了同样的操作,但它与你的代码相匹配,所以其他人更容易阅读。

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( now ) ;
int offsetInSeconds_NewYork = offset.getTotalSeconds() ;
int offsetInSeconds_MyDefaultZone = 
ZoneId.systemDefault().getRules().getOffset( now ).getTotalSeconds() ;
System.out.println(offsetInSeconds_MyDefaultZone / 60 /60);
System.out.println((offsetInSeconds_NewYork / 60 /60) - (offsetInSeconds_MyDefaultZone / 60 /60));

我需要这个的原因是我正在制作一个应用程序,该应用程序需要根据纽约时区保存预约。无论你在世界上的哪个地方,你的本地时区都会锁定在纽约早上8点到5点的预约时间。这允许客户端在匹配NY TZ.时查看其所在区域的时间

再次感谢这一点,因为我认为我在OP中发布的代码会减少我的PC(JVM)TZ与纽约的差异(.offset)。两者兼而有之,相减似乎是唯一真正的方法。遗憾的是,这不是Java的一个特性。但你可以在规则中看到我的困惑。getOffset(现在)可以更改为任何位置,但它从不将偏移调整为UTC以外的任何位置。很奇怪。

谢谢你推我的头。

虽然可以使用ZoneId#getRules#getOffset(LocalDateTime)获取时区偏移量,但为了简单起见,我更喜欢使用当前的ZoneId#getRules#getOffset(Instant)来获取此值。

演示:

import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
public class Main {
public static void main(String args[]) {
// Tests
ZoneId systemZoneId = ZoneId.systemDefault();
ZoneId zoneIdNy = ZoneId.of("America/New_York");
ZoneId zoneIdIndia = ZoneId.of("Asia/Kolkata");
System.out.printf("Difference between %s and %s: %s%n", systemZoneId.getId(), zoneIdNy.getId(),
timezoneOffsetDiffBewteen(systemZoneId, zoneIdNy));
System.out.printf("Difference between %s and %s: %s%n", systemZoneId.getId(), zoneIdIndia.getId(),
timezoneOffsetDiffBewteen(systemZoneId, zoneIdIndia));
}
static String timezoneOffsetDiffBewteen(ZoneId source, ZoneId target) {
Instant instant = Instant.now();
long offsetSecondsSource = source.getRules().getOffset(instant).getTotalSeconds();
long offsetSecondsTarget = target.getRules().getOffset(instant).getTotalSeconds();
long diff = offsetSecondsTarget - offsetSecondsSource;
Duration duration = Duration.ofSeconds(diff);
return String.format("%s%02d:%02d", diff < 0 ? "-" : "+", Math.abs(duration.toHoursPart()),
duration.toMinutesPart());
}
}

输出:

Difference between Europe/London and America/New_York: -05:00
Difference between Europe/London and Asia/Kolkata: +04:30

在线演示

跟踪:日期时间了解有关现代日期时间API*的更多信息。


*如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查通过降级提供的Java 8+API。请注意,Android 8.0奥利奥已经提供了对java.time的支持

您需要的是转换,而不是差异

我需要这个的原因是我正在制作一个需要保存的应用程序基于纽约时区的预约。无论你身在何处您的本地时区将锁定为的预约时间纽约时间上午8点至5点。这让客户可以看到它的时间当匹配纽约TZ.时,将在他们的区域

在Java中,在用户时区和美国/纽约时区之间转换时间比计算差值更容易。当你需要的东西很简单时,为什么要尝试复杂的东西?

我假设以下常数:

static final ZoneId SERVER_ZONE = ZoneId.of("America/New_York");
static final LocalTime OPENS_SERVER_TIME = LocalTime.of(8, 0);
static final LocalTime CLOSES_SERVER_TIME = LocalTime.of(17, 0); // 5 PM

要将时间从纽约时间转换为用户的时区,我们需要一个日期。纽约的UTC偏移量在标准时间和夏令时(DST)之间变化,用户所在的时区也可能如此(如果是,则转换日期不必重合)。

LocalDate date = LocalDate.of(2021, Month.OCTOBER, 20);
ZoneId userZone = ZoneId.systemDefault();
ZonedDateTime openInUserZone = date.atTime(OPENS_SERVER_TIME)
.atZone(SERVER_ZONE)
.withZoneSameInstant(userZone);

System.out.println(openInUserZone);

我在亚洲/杜尚别时区运行了这个,得到了这个输出:

2021-10-20T17:00+05:00[亚洲/杜尚别]

17:00 UTC偏移量+05:00与上午8点偏移量-04:00一致,即10月份纽约使用的偏移量。对于相反的转换,只需切换转换代码中的两个时区即可。

相关内容

  • 没有找到相关文章

最新更新