Перейти к основному содержимому

Отображение дат в часовом поясе пользователя

· 3 мин. чтения

1. Обзор

В этом выпуске тематического исследования приложения Reddit мы собираемся добавить посты планирования в соответствии с часовым поясом пользователя .

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

2. Новые пользовательские настройки — часовой пояс

Во-первых, мы добавим новое поле — часовой пояс — к нашим уже существующим настройкам:

@Entity
public class Preference {
...
private String timezone;
}

Затем мы просто настраиваем часовой пояс на странице пользовательских настроек , используя простой, но очень полезный плагин JQuery :

<select id="timezone" name="timezone"></select>
<script>
$(function() {
$('#timezone').timezones();
});
</script>

Обратите внимание, что часовой пояс по умолчанию — это часовой пояс сервера, который работает в формате UTC .

3. Контроллер

Теперь самое интересное. Нам нужно преобразовать даты из часового пояса пользователя в часовой пояс сервера :

@Controller
@RequestMapping(value = "/api/scheduledPosts")
public class ScheduledPostRestController {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm");

@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public void schedule(
@RequestBody Post post,
@RequestParam(value = "date") String date) throws ParseException
{
post.setSubmissionDate(
calculateSubmissionDate(date, getCurrentUser().getPreference().getTimezone()));
...
}

@RequestMapping(value = "/{id}", method = RequestMethod.PUT)
@ResponseStatus(HttpStatus.OK)
public void updatePost(
@RequestBody Post post,
@RequestParam(value = "date") String date) throws ParseException
{
post.setSubmissionDate(
calculateSubmissionDate(date, getCurrentUser().getPreference().getTimezone()));
...
}

private synchronized Date calculateSubmissionDate(String dateString, String userTimeZone)
throws ParseException {
dateFormat.setTimeZone(TimeZone.getTimeZone(userTimeZone));
return dateFormat.parse(dateString);
}
}

Преобразование довольно простое, но обратите внимание, что оно происходит только при операциях записи — сервер по-прежнему возвращает UTC для чтения.

Это совершенно нормально для нашего клиента, потому что мы будем выполнять преобразование в JS, но стоит понимать, что для операций чтения сервер по-прежнему возвращает даты в формате UTC .

4. Интерфейс

Теперь давайте посмотрим, как использовать часовой пояс пользователя во внешнем интерфейсе:

4.1. Показать сообщения

Нам нужно будет отображать дату отправки сообщения, используя часовой пояс пользователя:

<table><thead><tr>
<th>Post title</th>
<th>Submission Date
(<span id="timezone" sec:authentication="principal.preference.timezone">UTC</span>)</th>
</tr></thead></table>

А вот и наша функция loadPage() :

function loadPage(page){
...
$('.table').append('<tr><td>'+post.title+'</td><td>'+
convertDate(post.submissionDate)+'</td></tr>');
...
}
function convertDate(date){
var serverTimezone = [[${#dates.format(#calendars.createToday(), 'z')}]];
var serverDate = moment.tz(date, serverTimezone);
var clientDate = serverDate.clone().tz($("#timezone").html());
var myformat = "YYYY-MM-DD HH:mm";
return clientDate.format(myformat);
}

Moment.js помогает здесь с преобразованием часового пояса.

4.2. Запланировать новую публикацию

Нам также нужно изменить наш schedulePostForm.html :

Submission Date (<span sec:authentication="principal.preference.timezone">UTC</span>)
<input id="date" name="date" />

<script type="text/javascript">
function schedulePost(){
var data = {};
$('form').serializeArray().map(function(x){data[x.name] = x.value;});
$.ajax({
url: 'api/scheduledPosts?date='+$("#date").val(),
data: JSON.stringify(data),
type: 'POST',
contentType:'application/json',
success: function(result) {
window.location.href="scheduledPosts";
},
error: function(error) {
alert(error.responseText);
}
});
}
</script>

Наконец, нам также нужно изменить наш editPostForm.html , чтобы локализовать старое значение submissonDate :

$(function() {
var serverTimezone = [[${#dates.format(#calendars.createToday(), 'z')}]];
var serverDate = moment.tz($("#date").val(), serverTimezone);
var clientDate = serverDate.clone().tz($("#timezone").html());
var myformat = "YYYY-MM-DD HH:mm";
$("#date").val(clientDate.format(myformat));
});

5. Вывод

В этой простой статье мы представили простую, но очень полезную функцию в приложении Reddit — возможность видеть все в соответствии с вашим часовым поясом.

Это было одной из главных проблем при использовании приложения — тот факт, что все было в формате UTC. Теперь — все даты корректно отображаются в часовом поясе пользователя, как и должно быть.