有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于计算的java交换机时区

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

也就是说,开始{}和结束{}给出的时间应该被称为{},对于我们的主要业务部门,时间应该是{}到{}

服务器本身以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
}

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

@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) {

            }
        }

    }

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

另一个想法是扩展JodDateTime并用其所有重载重写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);
  }
}
  • 日期时间是“最终的”-(

因此,目前在生成期间名称(年、四分之一、月、周等)时,我总是需要手动处理它

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 + ")";
        }
    }

共 (1) 个答案

  1. # 1 楼答案

    我可能不会考虑设置默认值,因为这样您的代码中就会出现任何冗长的内容,这将有助于您了解到底发生了什么

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

    ...
    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 ...
    

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