This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/master by this push:
     new aacac5b  WW-5016 Support java8 date/time in date tag
     new c58e492  Merge pull request #330 from aleksandr-m/feature/java8_date
aacac5b is described below

commit aacac5b9fc0cbf4c191fcb2e8be232e3fa736dd0
Author: Aleksandr Mashchenko <amashche...@apache.org>
AuthorDate: Wed Feb 6 23:06:09 2019 +0200

    WW-5016 Support java8 date/time in date tag
---
 .../java/org/apache/struts2/components/Date.java   | 108 ++++++++++-----------
 .../apache/struts2/views/jsp/ui/DateTagTest.java   |  61 ++++++++++--
 2 files changed, 107 insertions(+), 62 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/components/Date.java 
b/core/src/main/java/org/apache/struts2/components/Date.java
index ba2c82d..a68e339 100644
--- a/core/src/main/java/org/apache/struts2/components/Date.java
+++ b/core/src/main/java/org/apache/struts2/components/Date.java
@@ -28,12 +28,15 @@ import 
org.apache.struts2.views.annotations.StrutsTagAttribute;
 
 import java.io.IOException;
 import java.io.Writer;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
-import java.util.TimeZone;
 
 /**
  * <!-- START SNIPPET: javadoc -->
@@ -220,11 +223,11 @@ public class Date extends ContextBean {
      * @param date the date
      * @return the date nicely
      */
-    public String formatTime(TextProvider tp, java.util.Date date) {
-        java.util.Date now = new java.util.Date();
+    public String formatTime(TextProvider tp, ZonedDateTime date) {
+        ZonedDateTime now = ZonedDateTime.now();
         StringBuilder sb = new StringBuilder();
-        List args = new ArrayList();
-        long secs = Math.abs((now.getTime() - date.getTime()) / 1000);
+        List<Object> args = new ArrayList<>();
+        long secs = Math.abs(now.toEpochSecond() - date.toEpochSecond());
         long mins = secs / 60;
         long sec = secs % 60;
         int min = (int) mins % 60;
@@ -267,7 +270,7 @@ public class Date extends ContextBean {
 
         args.clear();
         args.add(sb.toString());
-        if (date.before(now)) {
+        if (date.isBefore(now)) {
             // looks like this date is passed
             return tp.getText(DATETAG_PROPERTY_PAST, DATETAG_DEFAULT_PAST, 
args);
         } else {
@@ -275,54 +278,55 @@ public class Date extends ContextBean {
         }
     }
 
+    @Override
     public boolean end(Writer writer, String body) {
-        String msg;
-        java.util.Date date = null;
+        ZonedDateTime date = null;
+        final ZoneId tz = getTimeZone();
         // find the name on the valueStack
-        try {
-            //support Calendar also
-            Object dateObject = findValue(name);
-            if (dateObject instanceof java.util.Date) {
-                date = (java.util.Date) dateObject;
-            } else if (dateObject instanceof Calendar) {
-                date = ((Calendar) dateObject).getTime();
-            } else if (dateObject instanceof Long) {
-                date = new java.util.Date((long) dateObject);
-            } else {
-                if (devMode) {
-                    TextProvider tp = findProviderInStack();
-                    String developerNotification = "";
-                    if (tp != null) {
-                        developerNotification = findProviderInStack().getText(
-                                "devmode.notification",
-                                "Developer Notification:\n{0}",
-                                new String[]{
-                                        "Expression [" + name + "] passed to 
<s:date/> tag which was evaluated to [" + dateObject + "]("
-                                                + (dateObject != null ? 
dateObject.getClass() : "null") + ") isn't instance of java.util.Date nor 
java.util.Calendar nor long!"
-                                }
-                        );
-                    }
-                    LOG.warn(developerNotification);
-                } else {
-                    LOG.debug("Expression [{}] passed to <s:date/> tag which 
was evaluated to [{}]({}) isn't instance of java.util.Date nor 
java.util.Calendar nor long!",
-                            name, dateObject, (dateObject != null ? 
dateObject.getClass() : "null"));
+        Object dateObject = findValue(name);
+        if (dateObject instanceof java.util.Date) {
+            date = ((java.util.Date) dateObject).toInstant().atZone(tz);
+        } else if (dateObject instanceof Calendar) {
+            date = ((Calendar) dateObject).toInstant().atZone(tz);
+        } else if (dateObject instanceof Long) {
+            date = Instant.ofEpochMilli((long) dateObject).atZone(tz);
+        } else if (dateObject instanceof LocalDateTime) {
+            date = ((LocalDateTime) dateObject).atZone(tz);
+        } else if (dateObject instanceof Instant) {
+            date = ((Instant) dateObject).atZone(tz);
+        } else {
+            if (devMode) {
+                TextProvider tp = findProviderInStack();
+                String developerNotification = "";
+                if (tp != null) {
+                    developerNotification = findProviderInStack().getText(
+                            "devmode.notification",
+                            "Developer Notification:\n{0}",
+                            new String[]{
+                                    "Expression [" + name + "] passed to 
<s:date/> tag which was evaluated to [" + dateObject + "]("
+                                            + (dateObject != null ? 
dateObject.getClass() : "null") + ") isn't supported!"
+                            }
+                    );
                 }
+                LOG.warn(developerNotification);
+            } else {
+                LOG.debug("Expression [{}] passed to <s:date/> tag which was 
evaluated to [{}]({}) isn't supported!",
+                        name, dateObject, (dateObject != null ? 
dateObject.getClass() : "null"));
             }
-        } catch (Exception e) {
-            LOG.error("Could not convert object with key '{}' to a 
java.util.Date instance", name);
         }
 
         //try to find the format on the stack
         if (format != null) {
             format = findString(format);
         }
+        String msg;
         if (date != null) {
             TextProvider tp = findProviderInStack();
             if (tp != null) {
                 if (nice) {
                     msg = formatTime(tp, date);
                 } else {
-                    TimeZone tz = getTimeZone();
+                    DateTimeFormatter dtf;
                     if (format == null) {
                         String globalFormat = null;
 
@@ -335,23 +339,15 @@ public class Date extends ContextBean {
                         // DATETAG_PROPERTY
                         if (globalFormat != null
                                 && !DATETAG_PROPERTY.equals(globalFormat)) {
-                            SimpleDateFormat sdf = new 
SimpleDateFormat(globalFormat,
-                                    ActionContext.getContext().getLocale());
-                            sdf.setTimeZone(tz);
-                            msg = sdf.format(date);
+                            dtf = DateTimeFormatter.ofPattern(globalFormat, 
ActionContext.getContext().getLocale());
                         } else {
-                            DateFormat df = DateFormat.getDateTimeInstance(
-                                    DateFormat.MEDIUM, DateFormat.MEDIUM,
-                                    ActionContext.getContext().getLocale());
-                            df.setTimeZone(tz);
-                            msg = df.format(date);
+                            dtf = 
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
+                                    
.withLocale(ActionContext.getContext().getLocale());
                         }
                     } else {
-                        SimpleDateFormat sdf = new SimpleDateFormat(format, 
ActionContext
-                                .getContext().getLocale());
-                        sdf.setTimeZone(tz);
-                        msg = sdf.format(date);
+                        dtf = DateTimeFormatter.ofPattern(format, 
ActionContext.getContext().getLocale());
                     }
+                    msg = dtf.format(date);
                 }
                 if (msg != null) {
                     try {
@@ -369,15 +365,15 @@ public class Date extends ContextBean {
         return super.end(writer, "");
     }
 
-    private TimeZone getTimeZone() {
-        TimeZone tz = TimeZone.getDefault();
+    private ZoneId getTimeZone() {
+        ZoneId tz = ZoneId.systemDefault();
         if (timezone != null) {
             timezone = stripExpressionIfAltSyntax(timezone);
             String actualTimezone = (String) getStack().findValue(timezone, 
String.class);
             if (actualTimezone != null) {
                 timezone = actualTimezone;
             }
-            tz = TimeZone.getTimeZone(timezone);
+            tz = ZoneId.of(timezone);
         }
         return tz;
     }
diff --git 
a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java 
b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
index 185ee10..ccf5063 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java
@@ -19,11 +19,17 @@
 package org.apache.struts2.views.jsp.ui;
 
 import com.opensymphony.xwork2.ActionContext;
+
+import org.apache.struts2.TestAction;
 import org.apache.struts2.views.jsp.AbstractTagTest;
 import org.apache.struts2.views.jsp.DateTag;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
@@ -50,18 +56,33 @@ public class DateTagTest extends AbstractTagTest {
         assertEquals(formatted, writer.toString());
     }
 
+    public void testCustomGlobalFormatFormat() throws Exception {
+        String format = "yyyy/MM/dd hh:mm:ss";
+        Date now = new Date();
+        String formatted = new SimpleDateFormat(format).format(now);
+        context.put("myDate", now);
+
+        ((TestAction) 
action).setText(org.apache.struts2.components.Date.DATETAG_PROPERTY, format);
+
+        tag.setName("myDate");
+        tag.setNice(false);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(formatted, writer.toString());
+    }
+
     public void testCustomFormatWithTimezone() throws Exception {
         String format = "yyyy/MM/dd hh:mm:ss";
-        Date now = 
Calendar.getInstance(TimeZone.getTimeZone("UTC+1")).getTime();
+        Date now = 
Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime();
         SimpleDateFormat sdf = new SimpleDateFormat(format);
-        sdf.setTimeZone(TimeZone.getTimeZone("UTC+1"));
+        sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
         String formatted = sdf.format(now);
         context.put("myDate", now);
 
         tag.setName("myDate");
         tag.setNice(false);
         tag.setFormat(format);
-        tag.setTimezone("UTC+1");
+        tag.setTimezone("GMT+1");
         tag.doStartTag();
         tag.doEndTag();
         assertEquals(formatted, writer.toString());
@@ -69,12 +90,12 @@ public class DateTagTest extends AbstractTagTest {
 
     public void testCustomFormatWithTimezoneAsExpression() throws Exception {
         String format = "yyyy/MM/dd hh:mm:ss";
-        Date now = 
Calendar.getInstance(TimeZone.getTimeZone("UTC+2")).getTime();
+        Date now = 
Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime();
         SimpleDateFormat sdf = new SimpleDateFormat(format);
-        sdf.setTimeZone(TimeZone.getTimeZone("UTC+2"));
+        sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
         String formatted = sdf.format(now);
         context.put("myDate", now);
-        context.put("myTimezone", "UTC+2");
+        context.put("myTimezone", "GMT+2");
 
         tag.setName("myDate");
         tag.setNice(false);
@@ -114,6 +135,34 @@ public class DateTagTest extends AbstractTagTest {
         assertEquals(formatted, writer.toString());
     }
 
+    public void testCustomFormatLocalDateTime() throws Exception {
+        String format = "yyyy/MM/dd hh:mm:ss";
+        LocalDateTime date = LocalDateTime.now();
+        String formatted = date.format(DateTimeFormatter.ofPattern(format));
+        context.put("myDate", date);
+
+        tag.setName("myDate");
+        tag.setNice(false);
+        tag.setFormat(format);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(formatted, writer.toString());
+    }
+
+    public void testCustomFormatInstant() throws Exception {
+        String format = "yyyy/MM/dd hh:mm:ss";
+        Instant date = Instant.now();
+        String formatted = 
DateTimeFormatter.ofPattern(format).format(date.atZone(ZoneId.systemDefault()));
+        context.put("myDate", date);
+
+        tag.setName("myDate");
+        tag.setNice(false);
+        tag.setFormat(format);
+        tag.doStartTag();
+        tag.doEndTag();
+        assertEquals(formatted, writer.toString());
+    }
+
     public void testDefaultFormat() throws Exception {
         Date now = new Date();
         String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, 
DateFormat.MEDIUM,

Reply via email to