Вчера у меня была такая же проблема. Я живу в часовом поясе CET (Центральноевропейское время), и простое создание ячейки DateTime
отодвинуло время примерно на час.
Сначала я попытался установить часовой пояс на GMT
, как это предлагается в официальном руководстве.
final DateFormat valueFormatDate = new DateFormat( "dd.MM.yyyy HH:mm" );
valueFormatDate.getDateFormat().setTimeZone( TimeZone.getTimeZone( "GMT" ) );
Кажется, он не работает. Модификация времени была все та же. Поэтому я попытался установить правильный часовой пояс, соответствующий часовому поясу объекта Date
.
final DateFormat valueFormatDate = new DateFormat( "dd.MM.yyyy HH:mm" );
valueFormatDate.getDateFormat().setTimeZone( TimeZone.getTimeZone( "CET" ) );
Это сработало отлично, как я и ожидал. Но все не так просто, кроме часового пояса CET и CEST (Центральноевропейское летнее время), который перемещает время примерно на час. Когда я попытался использовать даты во время CEST, это снова не сработало, потому что к ожидаемой базе добавили один час. Я думаю, что было бы решением установить часовой пояс "CEST" вместо "CET" для них , но я не понял, как получить правильный часовой пояс из Calendar
, он всегда возвращал CET .
Во всяком случае, в конце концов я использовал не очень хорошее, но надежно работающее решение.
- У меня есть фабричный метод для ячейки даты, чтобы иметь конфигурацию в одном месте
- в этом методе я сначала конвертирую
Date
в часовой пояс GMT
- установить формат часового пояса на GMT
- отключить изменение часового пояса в ячейке
DateTime
.
Эти шаги не совсем чисты, но они работают как для CET, так и для дат CEST. Финальный код здесь:
public class DateUtils {
// formatter to convert from current timezone
private static final SimpleDateFormat DATE_FORMATTER_FROM_CURRENT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
// formatter to convert to GMT timezone
private static final SimpleDateFormat DATE_FORMATTER_TO_GMT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
static {
// initialize the GMT formatter
final Calendar cal = Calendar.getInstance( new SimpleTimeZone( 0, "GMT" ) );
DATE_FORMATTER_TO_GMT.setCalendar( cal );
}
public static Date toGMT( final Date base ) {
try {
// convert to string and after that convert it back
final String date = DATE_FORMATTER_FROM_CURRENT.format( base );
return DATE_FORMATTER_TO_GMT.parse( date );
} catch ( ParseException e ) {
log.error( "Date parsing failed. Conversion to GMT wasn't performed.", e );
return base;
}
}
}
А есть заводской метод
/** builds date cell for header */
static WritableCell createDate( final int column, final int row, final Date value ) {
final DateFormat valueFormatDate = new DateFormat( "dd.MM.yyyy HH:mm" );
valueFormatDate.getDateFormat().setTimeZone( TimeZone.getTimeZone( "GMT" ) );
final WritableCellFormat formatDate = new WritableCellFormat( valueFormatDate );
// create cell
return new DateTime( column, row, toGMT( value ), formatDate, DateTime.GMT );
}