Author: fanningpj
Date: Fri Jul 15 21:31:35 2022
New Revision: 1902754

URL: http://svn.apache.org/viewvc?rev=1902754&view=rev
Log:
[github-358] improve locking in CellDateFormatter. Thanks to XenoAmess. This 
closes #358

Modified:
    poi/trunk/poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java

Modified: 
poi/trunk/poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java?rev=1902754&r1=1902753&r2=1902754&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java 
(original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/format/CellDateFormatter.java 
Fri Jul 15 21:31:35 2022
@@ -40,11 +40,11 @@ public class CellDateFormatter extends C
     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 C
 
         @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');
-                    mStart = -1;
-                }
-                return part.toLowerCase(Locale.ROOT);
+                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;
-                hStart = pos;
-                hLen = part.length();
-                return part.toLowerCase(Locale.ROOT);
-
-            case 'd':
-            case 'D':
-                mStart = -1;
-                if (part.length() <= 2)
+                case 'h':
+                case 'H':
+                    mStart = -1;
+                    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');
+
+                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));
 
-                    return "a";
-                }
-                //noinspection fallthrough
+                        return "a";
+                    }
+                    //noinspection fallthrough
 
-            default:
-                return null;
+                default:
+                    return null;
             }
         }
 
@@ -242,11 +242,15 @@ public class CellDateFormatter extends C
      */
     @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);
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to