From 3a0fa9336e3eece10d0c9e87d106fca5b891d7e1 Mon Sep 17 00:00:00 2001 From: srosse <stephane.rosse@frentix.com> Date: Mon, 3 Dec 2018 18:46:35 +0100 Subject: [PATCH] OO-3760: pass the start/end date to add an event as ISO 8601 dates For the add operation, the start and end date is passed as ISO 8601 dates to prevent issues with timezone and daylight savings --- .../olat/commons/calendar/CalendarUtils.java | 78 +++++++++++++++++++ .../FullCalendarComponentRenderer.java | 5 +- .../ui/components/FullCalendarElement.java | 36 ++++++--- 3 files changed, 108 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/olat/commons/calendar/CalendarUtils.java b/src/main/java/org/olat/commons/calendar/CalendarUtils.java index d5da7238248..ccfc76cda10 100644 --- a/src/main/java/org/olat/commons/calendar/CalendarUtils.java +++ b/src/main/java/org/olat/commons/calendar/CalendarUtils.java @@ -37,6 +37,7 @@ import java.util.Locale; import org.olat.commons.calendar.model.KalendarEvent; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; import net.fortuna.ical4j.model.DateList; import net.fortuna.ical4j.model.Recur; @@ -48,6 +49,9 @@ public class CalendarUtils { private static final SimpleDateFormat ical4jFormatter = new SimpleDateFormat("yyyyMMdd"); private static final SimpleDateFormat occurenceDateTimeFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + private static final DateFormat iso8601Date = new SimpleDateFormat("yyyy-MM-dd"); + private static final DateFormat iso8601DateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + public static String getTimeAsString(Date date, Locale locale) { return DateFormat.getTimeInstance(DateFormat.SHORT, locale).format(date); } @@ -214,6 +218,80 @@ public class CalendarUtils { } } + /** + * The method will guess if the specified date as string + * is a date alone or a date with time. + * + * @param d The date as string in ISO 8601 format. + * @return The date object + * @throws ParseException + */ + public static Date parseISO8601(String d) throws ParseException { + Date date; + if(StringHelper.containsNonWhitespace(d)) { + if(d.indexOf('T') >= 0) { + date = parseISO8601Datetime(d); + } else { + date = parseISO8601Date(d); + } + } else { + date = null; + } + return date; + } + + /* + * Formats the given date with the ISO 8601 standard also known as 'date' + * See http://www.w3.org/TR/NOTE-datetime.html for more info. + * + * @param d the date to be formatted + * @return a String with the formatted date + */ + public static String formatISO8601Date(Date d) { + synchronized (iso8601Date) { + return iso8601Date.format(d); + } + } + + /** + * Parse the given date with the ISO 8601 standard also known as 'date' + * See http://www.w3.org/TR/NOTE-datetime.html for more info. + * + * @param d the date as string to be parsed + * @return The date + */ + public static Date parseISO8601Date(String d) throws ParseException { + synchronized (iso8601Date) { + return iso8601Date.parse(d); + } + } + + /** + * Formats the given date with the ISO 8601 standard also known as 'datetime' + * See http://www.w3.org/TR/NOTE-datetime.html for more info. + * + * @param d the date to be formatted + * @return a String with the formatted date and time + */ + public static String formatISO8601Datetime(Date d) { + synchronized (iso8601DateTime) { + return iso8601DateTime.format(d); + } + } + + /** + * Parse the given date with the ISO 8601 standard also known as 'datetime' + * See http://www.w3.org/TR/NOTE-datetime.html for more info. + * + * @param d the date as string to be parsed + * @return The date + */ + public static Date parseISO8601Datetime(String d) throws ParseException { + synchronized (iso8601DateTime) { + return iso8601DateTime.parse(d); + } + } + public static Date removeTime(Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); diff --git a/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarComponentRenderer.java b/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarComponentRenderer.java index 60e5b922ead..07a059a3516 100644 --- a/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarComponentRenderer.java +++ b/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarComponentRenderer.java @@ -124,6 +124,7 @@ public class FullCalendarComponentRenderer extends DefaultComponentRenderer { .append(" slotLabelFormat: '").append(ampm ? "h(:mm)tt" : "H.mm").append("',\n") .append(" },\n") .append(" },\n") + .append(" timezone: false,\n") .append(" firstDay:").append(firstDay).append(",\n") .append(" defaultDate: moment('").append(formatDate(cal.getTime())).append("'),\n") .append(" defaultView:'").append(fcC.getViewName()).append("',\n") @@ -184,9 +185,9 @@ public class FullCalendarComponentRenderer extends DefaultComponentRenderer { .append(" o_ffXHREvent(formNam, dispIdField, dispId, eventIdField, eventInt, true, false, false, 'evResize',calEvent.id,'dayDelta',delta.days(),'minuteDelta',minuteDelta,'allDay',allDay);\n") .append(" },\n") .append(" select: function(startDate, endDate, jsEvent, view) {\n") - .append(" var allDay = !startDate.hasTime();") + .append(" var allDay = !startDate.hasTime();\n") .append(FormJSHelper.generateXHRFnCallVariables(rootForm, formId, 1)) - .append(" o_ffXHREvent(formNam, dispIdField, dispId, eventIdField, eventInt, true, false, false, 'evAdd','new','start',startDate.valueOf(),'end',endDate.valueOf(),'allDay',allDay);\n") + .append(" o_ffXHREvent(formNam, dispIdField, dispId, eventIdField, eventInt, true, false, false, 'evAdd','new','start',startDate.toISOString(),'end',endDate.toISOString(),'allDay',allDay);\n") .append(" },\n") .append(" eventClick: function(calEvent, jsEvent, view) {\n") .append(FormJSHelper.generateXHRFnCallVariables(rootForm, formId, 1)) diff --git a/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarElement.java b/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarElement.java index 36a4e6a195a..1b34ef61bdf 100644 --- a/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarElement.java +++ b/src/main/java/org/olat/commons/calendar/ui/components/FullCalendarElement.java @@ -19,11 +19,13 @@ */ package org.olat.commons.calendar.ui.components; +import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.List; import org.olat.commons.calendar.CalendarManager; +import org.olat.commons.calendar.CalendarUtils; import org.olat.commons.calendar.model.KalendarEvent; import org.olat.commons.calendar.model.KalendarRecurEvent; import org.olat.commons.calendar.ui.events.CalendarGUIAddEvent; @@ -36,6 +38,8 @@ import org.olat.core.CoreSpringFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.impl.FormItemImpl; import org.olat.core.gui.translator.Translator; +import org.olat.core.logging.OLog; +import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.core.util.ValidationStatus; @@ -47,6 +51,8 @@ import org.olat.core.util.ValidationStatus; * */ public class FullCalendarElement extends FormItemImpl { + + private static final OLog log = Tracing.createLoggerFor(FullCalendarElement.class); private final FullCalendarComponent component; @@ -240,16 +246,28 @@ public class FullCalendarElement extends FormItemImpl { } private void doAdd(UserRequest ureq, String start, String end, String allDay) { - long startTime = -1; - if(StringHelper.isLong(start)) { - startTime = Long.parseLong(start); - } - long endTime = -1; - if(StringHelper.isLong(end)) { - endTime = Long.parseLong(end); + try { + boolean allDayEvent = "true".equalsIgnoreCase(allDay); + + Date startDate = null; + if(StringHelper.containsNonWhitespace(start)) { + startDate = CalendarUtils.parseISO8601(start); + } + Date endDate = null; + if(StringHelper.containsNonWhitespace(end)) { + endDate = CalendarUtils.parseISO8601(end); + if(allDayEvent && end.indexOf('T') == -1) { + // all day event ended the next day at 00:00:00, OpenOLAT want something which ends the same day + Calendar cal = Calendar.getInstance(); + cal.setTime(endDate); + cal.add(Calendar.DATE, -1); + endDate = cal.getTime(); + } + } + getRootForm().fireFormEvent(ureq, new CalendarGUIAddEvent(this, null, startDate, endDate, allDayEvent)); + } catch (ParseException e) { + log.error("", e); } - boolean allDayEvent = "true".equalsIgnoreCase(allDay); - getRootForm().fireFormEvent(ureq, new CalendarGUIAddEvent(this, null, new Date(startTime), new Date(endTime), allDayEvent)); } private void doSelect(UserRequest ureq, String eventId, String targetDomId) { -- GitLab