Я ищу правильный сериализуемый класс только для даты. Есть сервер в центральном часовом поясе, я хочу, чтобы пользователи в восточной части ввели дату как 2010-11-23, а пользователи в Тихоокеанском регионе видели ее как 2010-11-23 (и наоборот).
java.util.Date
— момент, зависящий от времени, поэтому он мне не подходит. Не желая изобретать велосипед, я решил попробовать Joda Time. Согласно обзору, LocalDate
- это «класс, представляющий локальную дату без времени (без часового пояса)» - как раз то, что мне нужно.
К сожалению, он не зависит от часового пояса. В базе у меня 2010-11-23. На сервере я преобразовываю его в LocalDate
с помощью new LocalDate(java.sql.Date)
. date.toString()
печатает 23 ноября 2010 г.
После десериализации на клиенте date.ToString()
печатает 2010-11-22, а date.getDayOfMonth()
— 22. Но date.toDateTimeAtStartOfDay()
выдает 2010-11-23T00:00:00.000-08:00.
Я делаю что-то неправильно? Есть ли в Joda правильный класс, нечувствительный к часовому поясу только для даты?
EDIT: в базе данных я использую столбец, нечувствительный к часовому поясу (DATE
в Postgres). Сервер находится в том же часовом поясе, что и база данных, поэтому он отлично считывает дату. Это не проблема. Я ищу тип Java, который когда-то был создан в одном часовом поясе, имеет одно и то же гражданское (частичное) значение даты во всех часовых поясах.
EDIT 2: на сервере все загружается правильно и имеет часовой пояс UTC. После расследования я думаю, что это ошибка в ISOChronology
. На клиенте распаковывается как America/Los_Angeles. Причина в том, что сериализация выполняется с помощью:
class ISOChronology {
// ...
private Object writeReplace() {
return new Stub(getZone());
}
private static final class Stub implements Serializable {
private static final long serialVersionUID = -6212696554273812441L;
private transient DateTimeZone iZone;
Stub(DateTimeZone zone) {
iZone = zone;
}
private Object readResolve() {
return ISOChronology.getInstance(iZone);
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(iZone);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
iZone = (DateTimeZone)in.readObject();
}
}
}
Удачи в сериализации с переходным полем.
Stub.iZone
является временным. - person Konrad Garus   schedule 24.11.2010