2011-06-28 2 views
0

Я разработал приложение FLEX для администрирования распределенных данных. Когда наши азиатские сотрудники укажу дату, она будет сохранена +1 день.FLEX: Обработка смещения временной зоны

Если я проверю свое смещение временной зоны +60, их смещение +520.

var dNow:Date = new Date(); 
    trace("Your time zone offset: " + dNow.getTimezoneOffset() + " minutes"); 

Я предполагаю, что это проблема? Если да, предложите ли вы исправить введенную дату на 460 минут, прежде чем отправлять ее на наш сервер для сохранения? Как это сделать?

ответ

1

Наконец я реализовал это решение:

получить данные с сервера, как ISO String (с ColdFusion на MS SQL Server):

SELECT CONVERT(varchar, CONTRACTED_DELIVERY, 104) AS CONTRACTED_DELIVERY 
FROM (...) 
WHERe (...) 

затем при получении его я преобразовать его в ValueObject (после рамки Кэрнгормс):

  if (obj.CONTRACTED_DELIVERY != null){ 
      this.CONTRACTED_DELIVERY = DateField.stringToDate(obj.CONTRACTED_DELIVERY,"DD.MM.YYYY"); 
     }else{ 
      this.CONTRACTED_DELIVERY = obj.CONTRACTED_DELIVERY; 
     } 

в отправить дата на сервере, как ISO Строка:

UPDATE (...) 
SET CONTRACTED_DELIVERY = <cfif productionDetails.CONTRACTED_DELIVERY EQ ''>null<cfelse>'#dateFormat(productionDetails.CONTRACTED_DELIVERY,"YYYY-MM-DD")#'</cfif> 
WHERE (...) 

Вы можете запросить дополнительную информацию!

5

Когда вы создаете объект Date в ActionScript, он будет внутренне хранить его значение в числовом значении UTC без времени, однако это значение будет рассчитано с использованием коррекции из-за смещения локального часового пояса/дневного сальдо клиента. Flash получает текущий часовой пояс базовой операционной системой, и в настоящее время нет возможности установить пользовательский часовой пояс.

Итак, если вы точно не находитесь в ситуации UTC + 0, фактическое значение даты будет содержать смещение определенного количества часов/минут.

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

Однако сохранение этого значения (например, отправка его в BlazeDS/LCDS для его сохранения в БД) и извлечение его из клиента с другим часовым поясом может вызвать неожиданный эффект, если вы не готовы к их обработке: например, если разница между поправками часового пояса двух клиентов отрицательная (например, -1 час), день, введенный как 28/06/2011, может отображаться как 27/06/2011 в компоненте DateField.

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

Простейшим решением будет установка всех клиентов на работу с общим часовым поясом, например часовым поясом сервера. К сожалению, текущая версия Flash Player не позволяет указать явный часовой пояс, и для реализации этой стратегии вам необходимо вручную установить внутренние значения UTC любой даты, созданной компонентами Flex, перед отправкой на сервер, чтобы компенсировать местное смещение часового пояса. Другим распространенным обходным решением является использование объектов Date и использование строкового представления ISO для дат.

В Adobe Bug Tracker вы найдете много информации (и некоторые идеи по управлению часовым поясом), см. Вопрос https://bugs.adobe.com/jira/browse/FP-175 с заголовком «Установить конкретный часовой пояс на flashplayer. Это позволит приложениям поддерживать одинаковый часовой пояс для всех клиентов в разных часовых поясах."

+0

Очень хороший ответ, однако, похоже, вам кажется, что особенно сложно установить правильную дату. Часто я позволяю серверу сохранять/отправлять универсальную строку даты (которая включает дату, время и смещение) и позволить 'DateFormatter.parseString' выполнять работу над моим классом команд. –

+0

Да, в зависимости от типа приложения, которое вы строите, использование строки вместо объектов Date для связи с сервером может быть жизнеспособным решением (я упомянул об этом в ответе, не вдаваясь в подробности). Однако, по моему опыту, может возникнуть сложность, когда у вас есть пользовательский сложный объект (структурированные DTOs/VO), а поле даты может быть вложен в эти структуры и при вычислении даты на стороне клиента. Я просто хотел предупредить, что независимо от выбранного решения хорошее понимание проблемы важно, чтобы избежать неприятных сюрпризов. –

1

раствор Blaze DS/Adobe LiveCycle DS на основе https://forums.adobe.com/thread/1076594:

услуги-config.xml

<service id="myProxyBootstrapService" class="org.myapp.flex.proxy.MyProxyBootstrapService"/> 

MyProxyBootstrapService.java

MyProxyBootstrapService extends AbstractBootstrapService { 

@Override 
public void initialize(String arg0, ConfigMap arg1) { 
    PropertyProxyRegistry registry = PropertyProxyRegistry.getRegistry(); 
    registry.register(Serializable.class, new DateProxy()); 
} 

DateProxy.java

public class DateProxy extends BeanProxy { 

private static final long serialVersionUID = 8097540028987261941L; 

private Integer serverOffset; 

public DateProxy() { 
    super(); 
} 

@Override 
public Object getValue(Object instance, String propertyName) { 
    Object result = super.getValue(instance, propertyName); 
    if (result instanceof Date) { 
     result = toDate(result, true); 
    } 
    return result; 
} 

@Override 
public void setValue(Object object, String propertyName, Object value) { 
    if (value instanceof Date) { 
     Date date = toDate(value, false); 
     super.setValue(object, propertyName, date); 
    } else { 
     super.setValue(object, propertyName, value); 
    } 
} 

private Date toDate(Object value, Boolean serverToClient) { 
    Date date = (Date) value; 
    Integer clientOffset = getClientOffset(); 
    Integer serverOffset = getServerOffset(); 
    if (clientOffset != null && !clientOffset.equals(serverOffset)) { 
     Calendar cal = new GregorianCalendar(TimeZone.getDefault()); 
     cal.setTime(date); 
     cal.add(Calendar.MINUTE, serverToClient ? clientOffset - serverOffset : serverOffset - clientOffset); 
     date.setTime(cal.getTimeInMillis()); 
    } 
    return date; 
} 

private Integer getClientOffset() { 
    return (Integer) FlexContext.getFlexSession().getAttribute("TIMEZONE_FLEX_OFFSET"); 
} 

private Integer getServerOffset() { 
    if (serverOffset == null) { 
     serverOffset = Calendar.getInstance().getTimeZone().getOffset(new Date().getTime())/1000/60 * -1; 
    } 
    return serverOffset; 
}