reddit-app-show-date-in-the-users-timezone
Displaying Dates in the Timezone of the User
1. Overview
In this installment of the Reddit app case study, we’re going to be adding the be scheduling post’s according to the user’s timezone.
Dealing with timezones is notoriously difficult and the technical options are wide open. Our first concern is that we need to show dates to the user according to their own (configurable) timezone. We also need to decide what format the date will be saved as, in the database.
2. A New User Preference – timezone
@Entity
public class Preference {
...
private String timezone;
}
We then simply make the timezone configurable in the user Preferences Page – leveraging a simple but very useful JQuery plugin:
<select id="timezone" name="timezone"></select>
<script>
$(function() {
$('#timezone').timezones();
});
</script>
Note that the default timezone is the server timezone – which runs on UTC.
3. The Controller
@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);
}
}
The conversion is pretty straightforward, but do note that it’s only happening on write operations – the server still returns UTC for reads.
That’s perfectly fine for our client, because we’ll do the conversion in JS – but it’s worth understanding that, for read operations, the server still returns UTC dates.
4. The Front-End
4.1. Display the Posts
<table><thead><tr>
<th>Post title</th>
<th>Submission Date
(<span id="timezone" sec:authentication="principal.preference.timezone">UTC</span>)</th>
</tr></thead></table>
And here is our function 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 helps here with the timezone conversion.
4.2. Schedule a New Post
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>
Finally – we also need to modify our editPostForm.html to localize the submissonDate old value:
$(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. Conclusion
In this simple article, we introduced a simple but highly useful feature into the Reddit app – the ability to see everything according to your own timezone.
This was one of the main pain points as I was using the app – the fact that everything was in UTC. Now – all dates are properly displayed in the timezone of the user, as they should be.