From 025c7d022dec2d88e710192a2fc47fb0fddfbb95 Mon Sep 17 00:00:00 2001
From: gnaegi <none@none>
Date: Fri, 11 Sep 2015 11:26:26 +0200
Subject: [PATCH] OO-1685 support long date formats in certificates, formatter
 and velocity

---
 .../velocity/VelocityRenderDecorator.java     | 46 +++++++++++
 .../java/org/olat/core/util/Formatter.java    | 79 +++++++++++++++----
 .../manager/CertificatePDFFormWorker.java     | 11 ++-
 .../manager/CertificatePhantomWorker.java     |  8 ++
 .../ui/_i18n/LocalStrings_de.properties       |  4 +-
 .../ui/_i18n/LocalStrings_en.properties       |  4 +-
 6 files changed, 131 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
index ea021d08a59..018443438f2 100644
--- a/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
+++ b/src/main/java/org/olat/core/gui/render/velocity/VelocityRenderDecorator.java
@@ -704,16 +704,62 @@ public class VelocityRenderDecorator implements Closeable {
 		return !vc.getContext().containsKey(key);
 	}
 	
+	/**
+	 * Formats the given date in a short format, e.g. 05.12.2015 or 12/05/2015
+	 * 
+	 * @param date the date
+	 * @return a String with the formatted date
+	 */
 	public String formatDate(Date date){
 		Formatter f = Formatter.getInstance(renderer.getTranslator().getLocale());
 		return f.formatDate(date);
 	}
 	
+	/**
+	 * Formats the given date in a medium sized format, e.g. 12. Dezember 2015 or December 12, 2015
+	 * 
+	 * @param date the date
+	 * @return a String with the formatted date
+	 */
+	public String formatDateLong(Date date){
+		Formatter f = Formatter.getInstance(renderer.getTranslator().getLocale());
+		return f.formatDateLong(date);
+	}
+	
+	/**
+	 * Formats the given date in a medium size with date and time, e.g. 05.12.2015 14:35
+	 * 
+	 * @param date the date
+	 * @return a String with the formatted date and time
+	 */
 	public String formatDateAndTime(Date date){
 		Formatter f = Formatter.getInstance(renderer.getTranslator().getLocale());
 		return f.formatDateAndTime(date);
 	}
 
+	/**
+	 * Formats the given date in a long size with date and time, e.g. Tuesday,
+	 * 10. September 2015, 3:48 PM
+	 * 
+	 * @param date
+	 *            the date
+	 * @return a String with the formatted date and time
+	 */
+	public String formatDateAndTimeLong(Date date) {
+		Formatter f = Formatter.getInstance(renderer.getTranslator().getLocale());
+		return f.formatDateAndTimeLong(date);	}
+
+	/**
+	 * formats the given time period so it is friendly to read
+	 * 
+	 * @param d the date
+	 * @return a String with the formatted time
+	 */
+	public String formatTime(Date date) {
+		Formatter f = Formatter.getInstance(renderer.getTranslator().getLocale());
+		return f.formatTime(date);
+	}
+	
 	public String formatBytes(long bytes) {
 		return Formatter.formatBytes(bytes);
 	}
diff --git a/src/main/java/org/olat/core/util/Formatter.java b/src/main/java/org/olat/core/util/Formatter.java
index 8ccb4586d81..9f8959d6e94 100644
--- a/src/main/java/org/olat/core/util/Formatter.java
+++ b/src/main/java/org/olat/core/util/Formatter.java
@@ -62,7 +62,9 @@ public class Formatter {
 	
 	private final Locale locale;
 	private final DateFormat shortDateFormat;
+	private final DateFormat longDateFormat;
 	private final DateFormat shortDateTimeFormat;
+	private final DateFormat longDateTimeFormat;
 	private final DateFormat shortTimeFormat;
 	private final DateFormat mediumTimeFormat;
 
@@ -71,19 +73,33 @@ public class Formatter {
 	 */
 	private Formatter(Locale locale) {
 		this.locale = locale;
+		// Date only formats
 		shortDateFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale);
 		shortDateFormat.setLenient(false);
+		if (shortDateFormat instanceof SimpleDateFormat) {
+			// by default year has only two digits, however most people prefer a four digits year, even in short format
+			SimpleDateFormat sdf = (SimpleDateFormat) shortDateFormat;
+			String pattern = sdf.toPattern().replaceAll("y+","yyyy");
+			sdf.applyPattern(pattern); 
+		}
+		longDateFormat = DateFormat.getDateInstance(DateFormat.LONG, locale);
+		longDateFormat.setLenient(false);
+		// Time only formats
+		shortTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
+		shortTimeFormat.setLenient(false);
 		mediumTimeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale);
 		mediumTimeFormat.setLenient(false);
+		// Date and time formats
 		shortDateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
 		shortDateTimeFormat.setLenient(false);
 		if (shortDateTimeFormat instanceof SimpleDateFormat) {
+			// by default year has only two digits, however most people prefer a four digits year, even in short format
 			SimpleDateFormat sdf = (SimpleDateFormat) shortDateTimeFormat;
 			String pattern = sdf.toPattern().replaceAll("y+","yyyy");
 			sdf.applyPattern(pattern); 
 		}
-		shortTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
-		shortTimeFormat.setLenient(false);
+		longDateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
+		longDateTimeFormat.setLenient(false);
 	}
 
 	/**
@@ -104,17 +120,31 @@ public class Formatter {
 	}
 
 	/**
-	 * formats the given date so it is friendly to read
+	 * Formats the given date in a short format, e.g. 05.12.2015 or 12/05/2015
 	 * 
-	 * @param d the date
+	 * @param date the date
 	 * @return a String with the formatted date
 	 */
-	public String formatDate(Date d) {
+	public String formatDate(Date date) {
+		if (date == null) return null;
 		synchronized (shortDateFormat) {
-			return shortDateFormat.format(d);
+			return shortDateFormat.format(date);
 		}
 	}
-	
+
+	/**
+	 * Formats the given date in a medium sized format, e.g. 12. Dezember 2015 or December 12, 2015
+	 * 
+	 * @param date the date
+	 * @return a String with the formatted date
+	 */
+	public String formatDateLong(Date date) {
+		if (date == null) return null;
+		synchronized (longDateFormat) {
+			return longDateFormat.format(date);
+		}
+	}
+
 	public Date parseDate(String val) throws ParseException {
 		synchronized (shortDateFormat) {
 			return shortDateFormat.parse(val);
@@ -124,28 +154,47 @@ public class Formatter {
 	/**
 	 * formats the given time period so it is friendly to read
 	 * 
-	 * @param d the date
+	 * @param date the date
 	 * @return a String with the formatted time
 	 */
-	public String formatTime(Date d) {
+	public String formatTime(Date date) {
+		if (date == null) return null;
 		synchronized (mediumTimeFormat) {
-			return mediumTimeFormat.format(d);
+			return mediumTimeFormat.format(date);
 		}
 	}
 
 	/**
-	 * formats the given date so it is friendly to read
+	 * Formats the given date in a short size with date and time, e.g.
+	 * 05.12.2015 14:35
 	 * 
-	 * @param d the date
+	 * @param date
+	 *            the date
 	 * @return a String with the formatted date and time
 	 */
-	public String formatDateAndTime(Date d) {
-		if (d == null) return null;
+	public String formatDateAndTime(Date date) {
+		if (date == null) return null;
 		synchronized (shortDateTimeFormat) {
-			return shortDateTimeFormat.format(d);
+			return shortDateTimeFormat.format(date);
 		}
 	}
 
+	/**
+	 * Formats the given date in a long size with date and time, e.g. Tuesday,
+	 * 10. September 2015, 3:48 PM
+	 * 
+	 * @param date
+	 *            the date
+	 * @return a String with the formatted date and time
+	 */
+	public String formatDateAndTimeLong(Date date) {
+		if (date == null) return null;
+		synchronized (longDateTimeFormat) {
+			return longDateTimeFormat.format(date);
+		}
+	}
+	
+	
 	/**
 	 * Generate a simple date pattern that formats a date using the locale of the
 	 * formatter
diff --git a/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java b/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java
index 01428840d6b..f9b87ee127e 100644
--- a/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java
+++ b/src/main/java/org/olat/course/certificate/manager/CertificatePDFFormWorker.java
@@ -161,10 +161,15 @@ public class CertificatePDFFormWorker {
 			Date from = entry.getLifecycle().getValidFrom();
 			String formattedFrom = format.formatDate(from);
 			fillField("from", formattedFrom, acroForm);
+			String formattedFromLong = format.formatDateLong(from);
+			fillField("fromLong", formattedFromLong, acroForm);
+
 
 			Date to = entry.getLifecycle().getValidTo();
 			String formattedTo = format.formatDate(to);
 			fillField("to", formattedTo, acroForm);
+			String formattedToLong = format.formatDateLong(to);
+			fillField("toLong", formattedToLong, acroForm);
 		}
 	}
 	
@@ -176,14 +181,16 @@ public class CertificatePDFFormWorker {
 		} else {
 			String formattedDateCertification= format.formatDate(dateCertification);
 			fillField("dateCertification", formattedDateCertification, acroForm);
-		}
+			String formattedDateCertificationLong= format.formatDateLong(dateCertification);
+			fillField("dateCertificationLong", formattedDateCertificationLong, acroForm);		}
 		
 		if(dateFirstCertification == null) {
 			fillField("dateFirstCertification", "", acroForm);
 		} else {
 			String formattedDateFirstCertification = format.formatDate(dateFirstCertification);
 			fillField("dateFirstCertification", formattedDateFirstCertification, acroForm);
-		}
+			String formattedDateFirstCertificationLong = format.formatDate(dateFirstCertification);
+			fillField("dateFirstCertificationLong", formattedDateFirstCertificationLong, acroForm);		}
 	}
 	
 	private void fillAssessmentInfos(PDAcroForm acroForm) throws IOException {
diff --git a/src/main/java/org/olat/course/certificate/manager/CertificatePhantomWorker.java b/src/main/java/org/olat/course/certificate/manager/CertificatePhantomWorker.java
index 898e1eeacb6..d60d66088e1 100644
--- a/src/main/java/org/olat/course/certificate/manager/CertificatePhantomWorker.java
+++ b/src/main/java/org/olat/course/certificate/manager/CertificatePhantomWorker.java
@@ -176,10 +176,14 @@ public class CertificatePhantomWorker {
 			Date from = entry.getLifecycle().getValidFrom();
 			String formattedFrom = format.formatDate(from);
 			context.put("from", formattedFrom);
+			String formattedFromLong = format.formatDateLong(from);
+			context.put("fromLong", formattedFromLong);
 
 			Date to = entry.getLifecycle().getValidTo();
 			String formattedTo = format.formatDate(to);
 			context.put("to", formattedTo);
+			String formattedToLong = format.formatDateLong(to);
+			context.put("toLong", formattedToLong);
 		}
 	}
 	
@@ -191,6 +195,8 @@ public class CertificatePhantomWorker {
 		} else {
 			String formattedDateCertification= format.formatDate(dateCertification);
 			context.put("dateCertification", formattedDateCertification);
+			String formattedDateCertificationLong= format.formatDateLong(dateCertification);
+			context.put("dateCertificationLong", formattedDateCertificationLong);
 		}
 		
 		if(dateFirstCertification == null) {
@@ -198,6 +204,8 @@ public class CertificatePhantomWorker {
 		} else {
 			String formattedDateFirstCertification = format.formatDate(dateFirstCertification);
 			context.put("dateFirstCertification", formattedDateFirstCertification);
+			String formattedDateFirstCertificationLong = format.formatDate(dateFirstCertification);
+			context.put("dateFirstCertificationLong", formattedDateFirstCertificationLong);
 		}
 	}
 	
diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
index 5028b9a97e4..9242c43e95b 100644
--- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties
@@ -17,9 +17,9 @@ chelp.eff3=<strong>PDF Zertifikat erzeugen:</strong> Sie k
 chelp.eff4=Als Vorlage für das Zertifikat dient in der Regel eine systemweite, vom Administrator festgelegte PDF-Vorlage. Wenn Sie eine eigene Vorlage verwenden möchten, können Sie diese unter <strong>Zertifikatvorlage</strong> hochladen. Eine PDF-Vorlage ist keine gewöhnliche PDF-Datei, sondern muss entweder ein mit z.B. Acrobat Pro hergestelltes PDF-Formular sein, oder eine HTML-Formular. Formularfelder müssen dann bestimmte Variablen enthalten, die vom System später durch die spezifischen Daten ersetzt werden.
 chelp.eff5=Hier eine Übersicht über die wichtigsten Variablen: 
 chelp.eff6=<em>Benutzer:</em> fullName, firstName, lastName, birthDay, institutionalName, orgUnit, studySubject
-chelp.eff7=<em>Kurs:</em> title, externalReference, authors, from (date) to (date), expenditureofwork, mainlanguage
+chelp.eff7=<em>Kurs:</em> title, externalReference, authors, from (date), fromLong (date), to (date), toLong (date), expenditureofwork, mainlanguage
 chelp.eff8=<em>Daten zur Leistung:</em> score, status
-chelp.eff9=<em>Daten zum Zertifikat:</em> dateFirstCertification, dateCertification
+chelp.eff9=<em>Daten zum Zertifikat:</em> dateFirstCertification, dateFirstCertificationLong, dateCertification, dateCertificationLong
 chelp.eff10=Sollten Sie eine Zertifikatvorlage wünschen, kontaktieren Sie uns unter support@frentix.com für einen Kostenvoranschlag für eine Vorlage gemäss Ihren individuellen Wünschen.
 chelp.eff11=<strong>Rezertifizierung erlauben:</strong> Dies gestattet die Ausstellung eines neuen Zertifikats nach Ablauf einer von Ihnen festgelegten Zeit.
 chelp.glo2=W\u00E4hlen Sie eine Lernressource vom Typ Glossar aus, um ein Glossar in diesen Kurs einzubinden.
diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
index a7f4112088b..8399aa61d97 100644
--- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties
@@ -17,9 +17,9 @@ chelp.eff3=<strong>Generate PDF certificate:</strong> Here you determine whether
 chelp.eff4=Usually, a systemwide PDF template, specified beforehand by an administrator, should be available. If however, you wish to utilize your own individual template, you can upload one in the <strong>Certificate template</strong> section.  A PDF template though is no ordinary PDF file, but has to be either a PDF form created with e.g. Acrobat Pro, or a HTML form. The form fields then must contain specific variables, which will be replaced by the system upon certificate creation with the respective values.
 chelp.eff5=Here a list of the most important variables:
 chelp.eff6=<em>User:</em> fullName, firstName, lastName, birthDay, institutionalName, orgUnit, studySubject
-chelp.eff7=<em>Course:</em> title, externalReference, authors, from (date) to (date), expenditureofwork, mainlanguage
+chelp.eff7=<em>Course:</em> title, externalReference, authors, from (date), fromLong (date), to (date), toLong (date), expenditureofwork, mainlanguage
 chelp.eff8=<em>Performance data:</em> score, status
-chelp.eff9=<em>Certificate data:</em> dateFirstCertification, dateCertification
+chelp.eff9=<em>Certificate data:</em> dateFirstCertification, dateFirstCertificationLong, dateCertification, dateCertificationLong
 chelp.eff10=If you would like to have such a certificate template, feel free to contact us via support@frentix.com in order to receive a cost estimate for a template according to your requirements.
 chelp.eff11=<strong>Allow re-certification:</strong> This enables the issuing of a new certificate after a specified period. 
 chelp.glo2=Please select a glossary from learning resources before linking it to your course.
-- 
GitLab