2015-08-09 2 views
3

Это мой первый вопрос на этом форуме, пожалуйста, будьте терпеливы со мной.save ZonedDateTime в MySQL и Glassfish

Oracle говорит: «ZonedDateTime - это дата и время с полным часовым поясом. Это может разрешить смещение в любой момент времени. Эмпирическое правило: если вы хотите представлять дату и время, не полагаясь на контекста конкретного сервера, вы должны использовать ZonedDateTime ». это именно то, что я хочу сделать, потому что приложение имеет дело с взаимодействиями во всем мире, но MySQL только сохраняет DATETIME как TIMESTAMP, но, по-видимому, сохраняет это как UTC, чтобы он мог быть преобразован в любой часовой пояс. Серверы, на которых мы будем работать, будут работать в нескольких часовых поясах, и мы не будем знать, какой из них будет выполняться там, где облачный провайдер будет динамически перемещать их на основе спроса и обслуживания.

Таким образом, поддержание даты/времени/зоны в этом приложении, по-видимому, идеально подходит для новой конструкции ZonedDateTime, но я неоднократно смущался, пытаясь сохранить все прямо между устаревшей датой, в которой PrimeFaces и другой код компонента все еще остаются поставляет и MySQL, который хочет иметь дело с Timestamps, который в конечном итоге возрастет в 2038 году.

Мы не хотим использовать какие-либо внешние библиотеки даты, такие как Joda или Apache.

Мой вопрос довольно прямолинейный, но ответ кажется неуловимым для меня, а нюансы, похоже, много: каковы наилучшие методы сохранения java ZonedDateTime в базе данных MySQL, считывая его обратно, чтобы работа может быть выполнена глобально пользователями через java мгновенные расчеты, которые выглядят прямо на локальном пользователе, и будут правильными независимо от местоположения сервера Glassfish или сервера MySQL, которые могут быть в разных часовых поясах друг от друга и со дня Cегодня?

ответ

0

Я думаю, что это потрясло нас так: MySQL сохраняет дату как UTC, когда она сохраняет как временную метку, пока я это делаю, неважно, где живет MySQL.

Glassfish может рассказать вам, где он живет, запрашивая сервер, но он также может установить свойство для домашнего офиса, который дает вам базу операций, которая будет соответствовать везде, где живет сервер. Вы можете сделать это в web.xml

боб
<context-param> 
    <param-name>GLASSFISH_HOME_TIME_ZONE</param-name> 
    <param-value>America/New_York</param-value> 
</context-param> 

данные должны сделать большую часть работы, с тем, что согласуется с данными по всем данным использует. Проблемы с библиотеками компонентов, которые либо не обновлены до ZonedDateTime, либо только частично обновлены, как правило, будут вызывать данные с помощью геттера, поэтому использование перегрузки должно позволить библиотекам компонентов находить конкретный метод, который он предпочитает. Я создал компонент данных, который выглядит примерно так:

общественного класса DataBean {

private final ZoneId GLASSFISH_HOME_TIME_ZONE = ZoneId.of(FacesContext.getCurrentInstance().getExternalContext().getInitParameter("GLASSFISH_HOME_TIME_ZONE")); 
private ZonedDateTime dateToUseInGlassfish = null; 

public DataBean (
    Timestamp dateFromMySQL) 
{ 
    if (dateFromMySQL == null) { 
     this.dateToUseInGlassfish = null; 
    } else { 
     this.dateToUseInGlassfish = LocalDateTime.ofInstant(dateFromMySQL.toInstant(), GLASSFISH_HOME_TIME_ZONE).atZone(GLASSFISH_HOME_TIME_ZONE); 
    } 
} 

/** Formatter for Date/Time */ 
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy ' at ' h:mm a z"); 

/** Formatter for Date only */ 
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); 

/** Get the date string formatted with date and time */ 
public String getDateToUseInGlassfishDateTimeFormatted() { 
    if (dateToUseInGlassfish == null) { return null; } 
    String formattedDate = dateTimeFormatter.format(dateToUseInGlassfish); 
    return formattedDate; 
} 

/** Get the date string formatted with date only */ 
public String getgetDateToUseInGlassfishDateFormatted() { 
    if (dateToUseInGlassfish == null) { return null; } 
    String formattedDate = dateFormatter.format(dateToUseInGlassfish); 
    return formattedDate; 
} 

/** Get the date ZDT formatted (for calculations) */ 
public ZonedDateTime getgetDateToUseInGlassfish() { 
    return dateToUseInGlassfish; 
} 

/** Get the date as Date (for component libraries that automatically fetch then throw up with ZDT) */ 
public Date getDateToUseInGlassfishDate() { 
    if (dateToUseInGlassfish == null) { return null; } 
    return Date.from(dateToUseInGlassfish.toInstant()); 
} 

/** Set the date from ZDT (results from calculations stored in bean) */ 
public void setDateToUseInGlassfish(ZonedDateTime dateToUseInGlassfish) { 
    this.dateToUseInGlassfish = dateToUseInGlassfish; 
} 

/** Set the date from Date with an automatic convert to ZDT */ 
public void setDateToUseInGlassfish(Date dateToUseInGlassfish) { 
    if (dateToUseInGlassfish == null) { 
     this.dateToUseInGlassfish = null; 
    } else { 
     this.dateToUseInGlassfish = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateToUseInGlassfish.getTime()), GLASSFISH_HOME_TIME_ZONE).atZone(GLASSFISH_HOME_TIME_ZONE); 
    } 
} 

Получение даты в качестве Timestamp из MySQL получает его в качестве точки UTC времени, и это выглядит примерно так:

ResultSet resultSet = preparedSelectQuoteSql.executeQuery()) { 
    while (resultSet.next()) { 
     quoteBean = new QuoteBean(
      resultSet.getTimestamp("MySQLDateColumn") 
     ); 
    } 
} 

Начало его вставленным/обновляют в MySQL из ZonedDateTime в метку времени, что MySQL будет автоматически преобразовать в UTC, так что мы можем позволить MySQL жить где мы хотим жить и читать обратно тот же момент времени:

if (insertValue instanceof ZonedDateTime) { 
    if (insertValue != null) { 
     Timestamp convertedDate = Timestamp.from(((ZonedDateTime) insertValue).toInstant()); 
     preparedStatement.setTimestamp(paramNumber, convertedDate); 
    } else { 
     preparedStatement.setNull (paramNumber, Types.TIMESTAMP); 
    } 
} 

Я думаю, что это работает, но я ПРИВЕТСТВУЮ с критикой.