gpt4 book ai didi

java - 切换时区进行计算

转载 作者:搜寻专家 更新时间:2023-11-01 03:39:05 31 4
gpt4 key购买 nike

我们的应用程序将所有日期存储在 UTC 时区中。然而,我们的主要业务部门位于“欧洲/柏林”时区(+2,+1 取决于夏令时)。因此,当我们确定某个时间跨度应该等于哪个“月”时,我们要使用那个时区。

即由开始 2013 年 10 月 31 日星期四 23:00:0 UTC 和结束 2013 年 11 月 29 日星期五 23:00:00 UTC 给出的时间应该是全局已知的作为 11 月 13 日,对于我们的主要业务部门,时间将是 2013 年 11 月 1 日,星期五,00:00:002013 年 11 月 30 日,星期五, 00:00:00

服务器本身在 UTC 中运行,因此我们必须在计算期间名称时切换时区。我们在后端使用 Joda Datetime,我总是可以这样做:

DateTime now = new DateTime();
now.withZone(DateTimeZone.forID("Europe/Berlin"));

但是有很多计算正在进行,我想知道是否有更好的方法在特定时区内进行所有计算?

如果它是一个独立的应用程序,可以使用类似的东西:

DateTimeZone old = DateTimeZone.getDefault();
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Berlin"));

//do all work

DateTimeZone.setDefault(old);

但是由于它是一个服务器环境,修改默认时区可能会导致在其他线程上发生的其他计算出现错误的结果。

所以,我想知道,是否没有像 java 中的 c# using 指令那样的东西?除了错误的语法,我正在寻找这样的东西:

using(DateTimeZone.forID("Europe/Berlin")){
//do all work, where JUST all DateTime usings inside this using
//Statement are affected
}

编辑:一些小测试显示了问题:即使在 2 个线程上运行时,两个线程都使用“默认”时区。因此,无论设置了 LAST 什么时区,都将用于两个线程。 (当然,这就是“默认”时区的用途。)

@Test
public final void testTimeZoneThreaded() {

Thread EuropeThread = new Thread(new Runnable() {
@Override
public void run() {
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Berlin"));

int i = 0;
while (i++ < 10) {
DateTime now = new DateTime();
System.out.println("It is now " + now + " in TimeZone " + DateTimeZone.getDefault().toString());

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});

Thread UTCThread = new Thread(new Runnable() {
@Override
public void run() {
DateTimeZone.setDefault(DateTimeZone.forID("UTC"));

int i = 0;
while (i++ < 10) {
DateTime now = new DateTime();
System.out.println("It is now " + now + " in TimeZone " + DateTimeZone.getDefault().toString());

try {
Thread.sleep(800);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});

EuropeThread.start();
UTCThread.start();

while (UTCThread.isAlive()) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {

}
}

}

能够在不同的线程上使用不同的默认值也会有所帮助。

另一个想法是扩展 JodaDateTime 并用它的所有重载覆盖 to string() 方法:

class MyDateTime extends DateTime{
@Override
public String toString(){
return super().withZone(DateTimeZone.for("Europe/Berlin")).toString();
}

@Override
public String toString(String format){
return super().withZone(DateTimeZone.for("Europe/Berlin")).toString(format);
}
}
  • DateTime 是“最终”... :-(

因此,目前我总是需要手动处理它,在生成期间名称(年、季度、月、周...)时

public String getMonthPeriodName() {
DateTime firstOfMonth = this.getPeriodStart().withZone(DateTimeZone.forID("Europe/Berlin")).dayOfMonth().withMinimumValue().millisOfDay().withMinimumValue();
DateTime lastOfMonth = this.getPeriodEnd().withZone(DateTimeZone.forID("Europe/Berlin")).dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue();

if (firstOfMonth.isEqual(getPeriodStart()) && lastOfMonth.isEqual(getPeriodEnd())) {
// full month.
return firstOfMonth.withZone(DateTimeZone.forID("Europe/Berlin")).toString("MMM yyyy", Locale.US);
} else {
// just partial month.
String Basename = firstOfMonth.withZone(DateTimeZone.forID("Europe/Berlin")).toString("MMM yyyy", Locale.US);
String f = getPeriodStart().withZone(DateTimeZone.forID("Europe/Berlin")).dayOfMonth().getAsShortText();
String t = getPeriodEnd().withZone(DateTimeZone.forID("Europe/Berlin")).dayOfMonth().getAsShortText();
return Basename + " (" + f + " to " + t + ")";
}
}

最佳答案

我可能不会考虑设置默认值,因为这样您就可以在代码中减少任何冗长的内容,从而帮助您了解真正发生的事情。

这是一个非常简单的建议,但也许您应该只使用局部变量。

...
DateTimeZone tz = DateTimeZone.forID("Europe/Berlin");
DateTime firstOfMonth = this.getPeriodStart().withZone(tz).dayOfMonth().withMinimumValue().millisOfDay().withMinimumValue();
DateTime lastOfMonth = this.getPeriodEnd().withZone(tz).dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue();
... etc ...

查看您的代码,我看到许多冗余,其中一些其他简单的局部变量可以更好地清理代码。

关于java - 切换时区进行计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19834468/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com