]> source.dussan.org Git - poi.git/commitdiff
[github-358] improve locking in CellDateFormatter. Thanks to XenoAmess. This closes...
authorPJ Fanning <fanningpj@apache.org>
Fri, 15 Jul 2022 21:31:35 +0000 (21:31 +0000)
committerPJ Fanning <fanningpj@apache.org>
Fri, 15 Jul 2022 21:31:35 +0000 (21:31 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1902754 13f79535-47bb-0310-9956-ffa450edef68

poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java

index 3644c84780d3bcd9137ca727a02dea90fd654600..f408450b48424520fec711f70e66a708d3d372bc 100644 (file)
@@ -40,11 +40,11 @@ public class CellDateFormatter extends CellFormatter {
     private String sFmt;
 
     private static final Calendar EXCEL_EPOCH_CAL =
-        LocaleUtil.getLocaleCalendar(1904, 0, 1);
+            LocaleUtil.getLocaleCalendar(1904, 0, 1);
 
     private static final int NUM_MILLISECONDS_IN_DAY = 1000 * 60 * 60 * 24;
 
-    private static /* final */ CellDateFormatter SIMPLE_DATE;
+    private static /* final */ volatile CellDateFormatter SIMPLE_DATE;
 
     class DatePartHandler implements CellFormatPart.PartHandler {
         private int mStart = -1;
@@ -54,79 +54,79 @@ public class CellDateFormatter extends CellFormatter {
 
         @Override
         public String handlePart(Matcher m, String part, CellFormatType type,
-                StringBuffer desc) {
+                                 StringBuffer desc) {
 
             int pos = desc.length();
             char firstCh = part.charAt(0);
             switch (firstCh) {
-            case 's':
-            case 'S':
-                if (mStart >= 0) {
-                    for (int i = 0; i < mLen; i++)
-                        desc.setCharAt(mStart + i, 'm');
+                case 's':
+                case 'S':
+                    if (mStart >= 0) {
+                        for (int i = 0; i < mLen; i++)
+                            desc.setCharAt(mStart + i, 'm');
+                        mStart = -1;
+                    }
+                    return part.toLowerCase(Locale.ROOT);
+
+                case 'h':
+                case 'H':
                     mStart = -1;
-                }
-                return part.toLowerCase(Locale.ROOT);
-
-            case 'h':
-            case 'H':
-                mStart = -1;
-                hStart = pos;
-                hLen = part.length();
-                return part.toLowerCase(Locale.ROOT);
-
-            case 'd':
-            case 'D':
-                mStart = -1;
-                if (part.length() <= 2)
+                    hStart = pos;
+                    hLen = part.length();
                     return part.toLowerCase(Locale.ROOT);
-                else
-                    return part.toLowerCase(Locale.ROOT).replace('d', 'E');
-
-            case 'm':
-            case 'M':
-                mStart = pos;
-                mLen = part.length();
-                // For 'm' after 'h', output minutes ('m') not month ('M')
-                if (hStart >= 0)
+
+                case 'd':
+                case 'D':
+                    mStart = -1;
+                    if (part.length() <= 2)
+                        return part.toLowerCase(Locale.ROOT);
+                    else
+                        return part.toLowerCase(Locale.ROOT).replace('d', 'E');
+
+                case 'm':
+                case 'M':
+                    mStart = pos;
+                    mLen = part.length();
+                    // For 'm' after 'h', output minutes ('m') not month ('M')
+                    if (hStart >= 0)
+                        return part.toLowerCase(Locale.ROOT);
+                    else
+                        return part.toUpperCase(Locale.ROOT);
+
+                case 'y':
+                case 'Y':
+                    mStart = -1;
+                    // See https://issues.apache.org/bugzilla/show_bug.cgi?id=53369
+                    if (part.length() == 1)
+                        part = "yy";
+                    else if (part.length() == 3)
+                        part = "yyyy";
                     return part.toLowerCase(Locale.ROOT);
-                else
-                    return part.toUpperCase(Locale.ROOT);
-
-            case 'y':
-            case 'Y':
-                mStart = -1;
-                // See https://issues.apache.org/bugzilla/show_bug.cgi?id=53369
-                if (part.length() == 1)
-                    part = "yy";
-                else if (part.length() == 3)
-                    part = "yyyy";
-                return part.toLowerCase(Locale.ROOT);
-
-            case '0':
-                mStart = -1;
-                int sLen = part.length();
-                sFmt = "%0" + (sLen + 2) + "." + sLen + "f";
-                return part.replace('0', 'S');
-
-            case 'a':
-            case 'A':
-            case 'p':
-            case 'P':
-                if (part.length() > 1) {
-                    // am/pm marker
+
+                case '0':
                     mStart = -1;
-                    showAmPm = true;
-                    showM = StringUtil.toLowerCase(part.charAt(1)).equals("m");
-                    // For some reason "am/pm" becomes AM or PM, but "a/p" becomes a or p
-                    amPmUpper = showM || StringUtil.isUpperCase(part.charAt(0));
+                    int sLen = part.length();
+                    sFmt = "%0" + (sLen + 2) + "." + sLen + "f";
+                    return part.replace('0', 'S');
 
-                    return "a";
-                }
-                //noinspection fallthrough
+                case 'a':
+                case 'A':
+                case 'p':
+                case 'P':
+                    if (part.length() > 1) {
+                        // am/pm marker
+                        mStart = -1;
+                        showAmPm = true;
+                        showM = StringUtil.toLowerCase(part.charAt(1)).equals("m");
+                        // For some reason "am/pm" becomes AM or PM, but "a/p" becomes a or p
+                        amPmUpper = showM || StringUtil.isUpperCase(part.charAt(0));
 
-            default:
-                return null;
+                        return "a";
+                    }
+                    //noinspection fallthrough
+
+                default:
+                    return null;
             }
         }
 
@@ -242,11 +242,15 @@ public class CellDateFormatter extends CellFormatter {
      */
     @Override
     public void simpleValue(StringBuffer toAppendTo, Object value) {
-        synchronized (CellDateFormatter.class) {
-            if (SIMPLE_DATE == null || !SIMPLE_DATE.EXCEL_EPOCH_CAL.equals(EXCEL_EPOCH_CAL)) {
-                SIMPLE_DATE = new CellDateFormatter("mm/d/y");
+        CellDateFormatter cellDateFormatter = SIMPLE_DATE;
+        if (cellDateFormatter == null) {
+            synchronized (CellDateFormatter.class) {
+                cellDateFormatter = SIMPLE_DATE;
+                if (cellDateFormatter == null) {
+                    SIMPLE_DATE = cellDateFormatter = new CellDateFormatter("mm/d/y");
+                }
             }
         }
-        SIMPLE_DATE.formatValue(toAppendTo, value);
+        cellDateFormatter.formatValue(toAppendTo, value);
     }
 }