Bug 59675

Summary: CellFormat with Chinese locale doesn't return date in Chinese
Product: POI Reporter: Trejkaz (pen name) <trejkaz>
Component: HSSFAssignee: POI Developers List <dev>
Status: NEW ---    
Severity: normal    
Priority: P2    
Version: 3.14-dev   
Target Milestone: ---   
Hardware: PC   
OS: Mac OS X 10.1   

Description Trejkaz (pen name) 2016-06-09 07:18:24 UTC
The exact version we're running with right now is 3.14-beta2.

Originally reported on 53494 as a NPE, but the new code doesn't produce the right result anyway, so I'm reporting it again.

    @Test
    public void testCellFormatWithChineseDateFormat() throws Exception
    {
        // -804 here means Chinese.
        CellFormat format = CellFormat.getInstance(
            "[$-804]mmmm dd yyyy  h:mm AM/PM");

        // Substitute whatever way you want to create the Date.
        // I left our test utilities and joda in the example.
        Date date = new DateTime(1973, 11, 27, 11, 28, 0,
                                 DateTestUtils.SYDNEY_TIME).toDate();

        // Since the format said to use Chinese, we expect Chinese.
        assertThat(
            format.apply(date).text,
            is(equalTo("十一月 27 1973  11:28 上午")));
    }

This fails because the locale is presumably ignored:

    Expected :十一月 27 1973  11:28 上午
    Actual   :November 27 1973  11:28 AM

Another developer noted that if you add this at the start of the text:

        LocaleUtil.setUserLocale(Locale.SIMPLIFIED_CHINESE);

(I would prefer a way to set the user locale which doesn't involve a static method, though, as static methods have a habit of poisoning later tests which run in unexpected ways. But setting that aside...)

With this, it does generate Chinese, but with a quirk where it seemingly replaces the last character with an M:

    Expected :十一月 27 1973  11:28 上午
    Actual   :十一月 27 1973  11:28 上M

I tracked this particular quirk down to CellDateFormatter which has some really baffling code going on.

            } else if(it1.getAttribute(Field.AM_PM) != null) {
                if(!doneAm1) {
                    if(this.showAmPm) {
                        if(this.amPmUpper) {
                            toAppendTo.append(Character.toUpperCase(ch1));
                            if(this.showM) {
                                toAppendTo.append('M');
                            }
                        } else {
                            toAppendTo.append(Character.toLowerCase(ch1));
                            if(this.showM) {
                                toAppendTo.append('m');
                            }
                        }
                    }

                    doneAm1 = true;
                }
            }

If I breakpoint before this code runs, the current contents of the buffer is exactly the expected result, and then this code goes and stamps an M at the end. (lol)

Ideally though I should not even have to set the user locale to get this test to pass. The cell format itself contains the locale which should be used to format the value, so that should be used.
Comment 1 Dominik Stadler 2018-10-21 18:05:08 UTC
Support for locales in formats is not yet implemented, see org/apache/poi/ss/format/CellFormatPart.java:305