Вы находитесь здесь:
Пример кода с регионально отформатированными данными
Просмотрите примеры кода, обрабатывающего данные, которые можно форматировать на основе региона пользователя. Узнайте, как код может взломаться, если он зависит от определенного формата для дат, времени и валют. Ознакомьтесь с примерами решения этих проблем посредством стандартных методов обработки данных данных.
Требуемые версии
| Доступно в версиях: Salesforce Classic и Lightning Experience |
| Доступно в версиях: все версии |
Форматы валюты, даты, времени, даты и времени, целого числа, имени и адреса могут меняться при изменении региона пользователем. При включении региональных форматов международных компонентов Юникода (ICU) форматы даты, времени, даты и времени, целого числа и валюты меняются для некоторых регионов.
Рассмотрим некоторые примеры кода, обрабатывающие данные типы данных и ошибки, которые могут произойти, если мы не используем регионально-нейтральные методы в коде.
Извлечение компонентов даты
В данном примере мы хотим проверить дату: 12 октября 2021 года. Чтобы пример был простым, мы отображаем только часть процесса, где код проверяет значения месяца, дня и года. Значение месяца должно быть меньше или равно 12. Значение дня должно быть меньше или равно 31. А значение года должно содержать ровно 4 цифры. Только даты, прошедшие все три теста, потом извлекаются в соответствующие значения для дополнительной обработки.
Ниже указан пример, использующий классы схемы Apex и совпадения для определения даты. Сопоставление схем предполагает формат даты ММ/дд/ггг.
Date myDate = Date.newInstance(2021, 10, 20);
String formattedDate = myDate.format();
//Simple regex not having all validations for days in months nor accounting for leap year
Pattern datePattern = Pattern.compile('(0?[1-9]|1[0-2])\\/(0?[1-9]|[2][0-9]|3[01])\\/([0-9]{4})');
Matcher matcher = datePattern.matcher(formattedDate);
if(matcher.matches()) {
Integer day = Integer.valueOf((matcher.group(1))); //10
Integer month = Integer.valueOf((matcher.group(2))); //20
Integer year = Integer.valueOf((matcher.group(3))); //2021
// Further validation logic for max days in month/ leap year and post processing
}
Код Apex форматирует дату в соответствии с регионом пользователя контекста. В данном примере пользователь контекста выбрал регион «Испанский (США) [es_US]».
Если региональные форматы ICU включены, эта проверка не выполняется. Формат ICU для региона пользователя отличается от соответствующего формата Инструментального набора для разработки Java-приложений Oracle (JDK).
- Короткий формат даты JDK для es_US: 10/20/2021
- Короткий формат даты ICU для es_US: 20/10/2021
Метод format() класса Apex Date возвращает дату в виде строки посредством региона пользователя контекста. В данном случае, поскольку региональные форматы ICU включены, а регион пользователя является es_US, возвращается 20/10/2021.
Код потом использует размещение в выводе даты для назначения значений месяца, дня и года в формате ММ/дд/ггг. Таким образом, код назначает 20 месяцем, а поскольку 20 больше 12, совпадение схемы неправильно определяет недействительность этой даты.
Во избежание подобного рода проблем используйте встроенные методы Apex для извлечения обязательных значений. В данном случае month(), day() и year().
Ниже указан пример использования этих методов для установки значений месяца, дня и года.
Date myDate = Date.newInstance(2021, 10, 20);
// assign month, day, and year values for validation
Integer month = myDate.month(); //10
Integer day = myDate.day(); //20
Integer year = myDate.year(); //2021
// Further validation logic
Проверка значения даты и времени
Данный пример Apex использует метод Datetime.parse для создания даты и времени из строки. Переданное значение соответствует региональному формату JDK для региона «Английский (США) [en_US]».
Эта проверка не выполняется при включении региональных форматов ICU, поскольку формат даты и времени для en_US отличается в JDK и ICU. Формат ICU содержит запятую после даты.
- Формат даты и времени JDK для es_US: 14.10.2011 11:46
- Формат даты и времени ICU для es_US: 14.10.2011, 11:46
Datetime dt = DateTime.parse('10/14/2011 11:46 AM');
String myDtString = dt.format();
system.assertEquals(myDtString, '10/14/2011, 11:46 AM');
Чтобы исправить эту проблему, обновите переданное значение в региональном формате ICU. Если внешняя система передает значение, обратитесь к отправителю для обновления формата исходных данных. При любой возможности попросите отправителя отправить дату в регионально-нейтральном формате. Рекомендуем обрабатывать обновления формата таким образом, поскольку регионально-нейтральные форматы не требуют обновления кода при изменении формата.
Однако, не всегда возможно заставить отправителя обновить формат данных, переданных в вашу организацию. Если это происходит, поскольку вы знаете формат отправляемых данных, их можно переформатировать. В этих случаях преобразуйте данные в регионально-нейтральный формат.
Ниже указаны два распространенных метода, используемых для форматирования даты и времени в Apex. При использовании двух этих методов, итоговые дата и время будут регионально-нейтральными: они отображаются в выбранном регионе пользователя. Дополнительные сведения о методах, доступных для всех форматов, см. в Справочном руководстве Apex.
- Извлеките компоненты даты в отдельные параметры: год, месяц, день, часы, минуты и секунды. Потом, чтобы создать регионально- нейтральную дату, используйте метод
DateTime.newInstanceGMT()класса Datetime Apex.//Before using the code below, set the year, month, day, hour, minutes, and seconds components //by extracting values from the passed date and complete any necessary validation //set the datetime value by passing the parameters DateTime myDt = DateTime.newInstanceGMT(year, month, day, hour, minutes, seconds); - Переформатируйте переданные данные в стандартном формате даты гггг-ММ-дд ЧЧ:мм:сс в региональном часовом поясе. Потом, чтобы создать регионально-нейтральную дату, используйте метод
valueOf(String dateTimeString)класса Datetime.//Before using the code below, convert the passed datetime data to a string in the format yyyy-MM-dd HH:mm:ss //and assign that value to the stringDate parameter //set the datetime value by passing the string DateTime myDt = date.valueOf(stringDate);
Этот метод преобразования форматов работает до тех пор, пока формат данных, переданных в организацию, не изменится. Если внешний источник обновляет их формат, необходимо обновить методы, используемые для извлечения или преобразования данных.
Передача времени во внешнюю систему
В данном простом примере событие происходит в 15:30 по Гринвичу 18 ноября 2021 года. Мы хотим передать дату и время как отдельные значения во внешнюю систему.
//create Datetime to pass externally in GMT
DateTime event1_dt = DateTime.newInstanceGMT(2021, 11, 18, 15, 30, 0);
//split into event date and event time for external system
Date event1_date = event1_dt.date();
Time event1_time = event1_dt.time();
Этот код работает, если внешняя система ожидает дату и время в нейтральных форматах. Но что делать, если внешней системе нужны дата и время события в определенном формате? Предположим, что внешняя система ожидает дату и время в следующих форматах: 18/11/2021 и 15:30.
В этом случае, чтобы применить ожидаемые форматы к дате и времени события, используйте метод format() даты и времени.
//create Datetime to pass externally
DateTime event1_dt = DateTime.newInstance(2021, 11, 18, 15, 30, 0);
//split into event date and event time for external system, applying expected format
String event1_date = event1_dt.format('dd/MM/yyyy');
String event1_time = event1_dt.format('h:mm a');
