Наше приложение хранит все даты в часовой пояс UTC. Однако наша основная бизнес-единица находится в часовом поясе «Европа/Берлин» (+2, +1 в зависимости от летнего времени). Поэтому, когда мы определяем, какой «месяц» определенный период времени должен равняться, мы хотим использовать THAT Timezone.Переключатель Часовой пояс для расчета
I.e. Период задается в начале Thursday, 31 October 2013, 23:00:0 UTC
и в конце Friday, 29 November 2013, 23:00:00 UTC
должны пчелы globaly известный как Nov 13
, как и для нашего Крупной Business Unit, Таймс будет Friday, 1 November 2013, 00:00:00
к Friday, 30 November 2013, 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);
Однако поскольку это серверная среда, изменение значения по умолчанию Timezone может привести к ошибочным результатам на других расчетов, происходящих на других потоки.
так, интересно, если нет ничего похожего на директиву C#, использующую java? Помимо неправильного синтаксиса я искал что-то вроде этого:
using(DateTimeZone.forID("Europe/Berlin")){
//do all work, where JUST all DateTime usings inside this using
//Statement are affected
}
Edit: Некоторые Маленький тест показывает проблему: Даже при работе на 2 нитки, «по умолчанию» TimeZone используется в обоих потоках. Итак, независимо от того, какой часовой пояс установлен, LAST будет использоваться для обоих потоков. (Конечно, это то, что «по умолчанию» Timezone для.)
@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 и переопределить в строке() метод со всеми его перегрузками:
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 + ")";
}
}
Не уверен, что ИСПОЛЬЗОВАНИЕ или его эквивалент в java является правильным ответом на эту проблему: http: // stackoverflow.com/questions/2943542/using-keyword-in-java –
@VladimirBozic Вот почему я написал * поиск чего-то вроде * - не уверен, если это возможно. Было бы также полезно начать поток в определенный часовой пояс или что-либо подобное с таким же эффектом. – dognose
Глобальный часовой пояс для Joda статичен и изменчив: как вы покажете его в своем примере, значение доступно для всех потоков. – zenbeni