include/vcl/toolkit/field.hxx |    2 
 vcl/source/control/field2.cxx |  147 ++++++++++++++++++++++++++++++++----------
 2 files changed, 115 insertions(+), 34 deletions(-)

New commits:
commit ccc48da9f9de2c93c01b9571f98221ff2eb07275
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Jul 5 18:37:37 2021 +0200
Commit:     Eike Rathke <er...@redhat.com>
CommitDate: Mon Jul 5 23:40:53 2021 +0200

    DateFormatter: make TextToDate() long date calendar aware, tdf#125035
    
    Using number formatter to display long date now can generate any
    arbitrary date string in any calendar known to the locale. Cope
    with non-default non-Gregorian calendars when parsing such string
    back to a date and convert to Gregorian for the calendar widget.
    
    This currently relies on month names being different between
    calendars, which isn't fail-proof but at least works for the ar_DZ
    Hijri->Gregorian case.
    
    A better approach would be to remember the calendar used in the
    number formatter output, but that's not available (yet?).
    
    Change-Id: I829655275de4d1983b7e453624efca967b16a3bd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118449
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 28859cd06cc699708bb43cb5e4ac7077d3a10f5b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118428

diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx
index 6ed04e3a16ee..033905250b12 100644
--- a/vcl/source/control/field2.cxx
+++ b/vcl/source/control/field2.cxx
@@ -36,6 +36,7 @@
 #include <svdata.hxx>
 
 #include <com/sun/star/i18n/XCharacterClassification.hpp>
+#include <com/sun/star/i18n/CalendarFieldIndex.hdl>
 
 #include <unotools/localedatawrapper.hxx>
 #include <unotools/calendarwrapper.hxx>
@@ -1201,20 +1202,83 @@ static bool ImplCutMonthName( OUString& rStr, 
std::u16string_view _rLookupMonthN
     return index >= 0;
 }
 
-static sal_uInt16 ImplCutMonthFromString( OUString& rStr, const 
CalendarWrapper& rCalendarWrapper )
+static sal_uInt16 ImplGetMonthFromCalendarItem( OUString& rStr, const 
uno::Sequence< i18n::CalendarItem2 >& rMonths )
 {
-    // search for a month' name
-    for ( sal_uInt16 i=1; i <= 12; i++ )
+    const sal_uInt16 nMonths = rMonths.getLength();
+    for (sal_uInt16 i=0; i < nMonths; ++i)
     {
-        OUString aMonthName = rCalendarWrapper.getMonths()[i-1].FullName;
         // long month name?
-        if ( ImplCutMonthName( rStr, aMonthName ) )
-            return i;
+        if ( ImplCutMonthName( rStr, rMonths[i].FullName ) )
+            return i+1;
 
         // short month name?
-        OUString aAbbrevMonthName = 
rCalendarWrapper.getMonths()[i-1].AbbrevName;
-        if ( ImplCutMonthName( rStr, aAbbrevMonthName ) )
-            return i;
+        if ( ImplCutMonthName( rStr, rMonths[i].AbbrevName ) )
+            return i+1;
+    }
+    return 0;
+}
+
+static sal_uInt16 ImplCutMonthFromString( OUString& rStr, OUString& 
rCalendarName,
+        const LocaleDataWrapper& rLocaleData, const CalendarWrapper& 
rCalendarWrapper )
+{
+    const OUString aDefaultCalendarName( rCalendarWrapper.getUniqueID());
+    rCalendarName = aDefaultCalendarName;
+
+    // Search for a month name of the loaded default calendar.
+    const uno::Sequence< i18n::CalendarItem2 > aMonths = 
rCalendarWrapper.getMonths();
+    sal_uInt16 nMonth = ImplGetMonthFromCalendarItem( rStr, aMonths);
+    if (nMonth > 0)
+        return nMonth;
+
+    // And also possessive genitive and partitive month names.
+    const uno::Sequence< i18n::CalendarItem2 > aGenitiveMonths = 
rCalendarWrapper.getGenitiveMonths();
+    if (aGenitiveMonths != aMonths)
+    {
+        nMonth = ImplGetMonthFromCalendarItem( rStr, aGenitiveMonths);
+        if (nMonth > 0)
+            return nMonth;
+    }
+    const uno::Sequence< i18n::CalendarItem2 > aPartitiveMonths = 
rCalendarWrapper.getPartitiveMonths();
+    if (aPartitiveMonths != aMonths)
+    {
+        nMonth = ImplGetMonthFromCalendarItem( rStr, aPartitiveMonths);
+        if (nMonth > 0)
+            return nMonth;
+    }
+
+    // Check if there are more calendars and try them if so, as the long date
+    // format is obtained from the number formatter this is possible (e.g.
+    // ar_DZ "[~hijri] ...")
+    const uno::Sequence< i18n::Calendar2 > aCalendars =  
rLocaleData.getAllCalendars();
+    if (aCalendars.getLength() > 1)
+    {
+        for (const auto& rCalendar : aCalendars)
+        {
+            if (rCalendar.Name != aDefaultCalendarName)
+            {
+                rCalendarName = rCalendar.Name;
+
+                nMonth = ImplGetMonthFromCalendarItem( rStr, rCalendar.Months);
+                if (nMonth > 0)
+                    return nMonth;
+
+                if (rCalendar.Months != rCalendar.GenitiveMonths)
+                {
+                    nMonth = ImplGetMonthFromCalendarItem( rStr, 
rCalendar.GenitiveMonths);
+                    if (nMonth > 0)
+                        return nMonth;
+                }
+
+                if (rCalendar.Months != rCalendar.PartitiveMonths)
+                {
+                    nMonth = ImplGetMonthFromCalendarItem( rStr, 
rCalendar.PartitiveMonths);
+                    if (nMonth > 0)
+                        return nMonth;
+                }
+
+                rCalendarName = aDefaultCalendarName;
+            }
+        }
     }
 
     return ImplCutNumberFromString( rStr );
@@ -1251,26 +1315,50 @@ bool DateFormatter::TextToDate(const OUString& rStr, 
Date& rDate, ExtDateFieldFo
 
     if ( eDateOrder == ExtDateFieldFormat::SystemLong )
     {
+        OUString aCalendarName;
         DateOrder eFormat = rLocaleDataWrapper.getLongDateOrder();
         switch( eFormat )
         {
             case DateOrder::MDY:
-                nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
+                nMonth = ImplCutMonthFromString( aStr, aCalendarName, 
rLocaleDataWrapper, rCalendarWrapper );
                 nDay = ImplCutNumberFromString( aStr );
                 nYear  = ImplCutNumberFromString( aStr );
                 break;
             case DateOrder::DMY:
                 nDay = ImplCutNumberFromString( aStr );
-                nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
+                nMonth = ImplCutMonthFromString( aStr, aCalendarName, 
rLocaleDataWrapper, rCalendarWrapper );
                 nYear  = ImplCutNumberFromString( aStr );
                 break;
             case DateOrder::YMD:
             default:
                 nYear = ImplCutNumberFromString( aStr );
-                nMonth = ImplCutMonthFromString( aStr, rCalendarWrapper );
+                nMonth = ImplCutMonthFromString( aStr, aCalendarName, 
rLocaleDataWrapper, rCalendarWrapper );
                 nDay  = ImplCutNumberFromString( aStr );
                 break;
         }
+        if (aCalendarName != "gregorian")
+        {
+            // Calendar widget is Gregorian, convert date.
+            // Need full date.
+            bError = !nDay || !nMonth || !nYear;
+            if (!bError)
+            {
+                CalendarWrapper aCW( rLocaleDataWrapper.getComponentContext());
+                aCW.loadCalendar( aCalendarName, 
rLocaleDataWrapper.getLoadedLanguageTag().getLocale());
+                aCW.setDateTime(0.5);   // get rid of current time, set some 
day noon
+                aCW.setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDay);
+                aCW.setValue( i18n::CalendarFieldIndex::MONTH, nMonth - 1);
+                aCW.setValue( i18n::CalendarFieldIndex::YEAR, nYear);
+                bError = !aCW.isValid();
+                if (!bError)
+                {
+                    Date aDate = aCW.getEpochStart() + aCW.getDateTime();
+                    nYear = aDate.GetYear();
+                    nMonth = aDate.GetMonth();
+                    nDay = aDate.GetDay();
+                }
+            }
+        }
     }
     else
     {
commit e8b1f2197776a08ac0b3d7e9a754c3e92327345a
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Jul 5 14:24:27 2021 +0200
Commit:     Eike Rathke <er...@redhat.com>
CommitDate: Mon Jul 5 23:40:33 2021 +0200

    Pass Formatter::StaticFormatter also from weld:DateFormatter, tdf#125035
    
    Change-Id: I8e6b0e581b9522fb04225fc945e579406a4be208
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118438
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 0335a319c5662f0b849a2231e48338dfeb6aa845)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118427

diff --git a/include/vcl/toolkit/field.hxx b/include/vcl/toolkit/field.hxx
index d6ae05f51fc5..1eb55fabfd29 100644
--- a/include/vcl/toolkit/field.hxx
+++ b/include/vcl/toolkit/field.hxx
@@ -417,7 +417,7 @@ protected:
     SAL_DLLPRIVATE bool     ImplAllowMalformedInput() const;
 
 public:
-    static OUString         FormatDate(const Date& rNewDate, 
ExtDateFieldFormat eFormat, const LocaleDataWrapper& rLocaleData, 
CalendarWrapper& rCalendarWrapper, const Formatter::StaticFormatter* 
pStaticFormatter = nullptr);
+    static OUString         FormatDate(const Date& rNewDate, 
ExtDateFieldFormat eFormat, const LocaleDataWrapper& rLocaleData, const 
Formatter::StaticFormatter& rStaticFormatter);
     static bool             TextToDate(const OUString& rStr, Date& rTime, 
ExtDateFieldFormat eFormat, const LocaleDataWrapper& rLocaleDataWrapper, const 
CalendarWrapper& rCalendarWrapper);
     static int              GetDateArea(ExtDateFieldFormat eFormat, const 
OUString& rText, int nCursor, const LocaleDataWrapper& rLocaleDataWrapper);
 
diff --git a/vcl/source/control/field2.cxx b/vcl/source/control/field2.cxx
index 603415672f38..6ed04e3a16ee 100644
--- a/vcl/source/control/field2.cxx
+++ b/vcl/source/control/field2.cxx
@@ -1388,8 +1388,8 @@ namespace
 }
 
 OUString DateFormatter::FormatDate(const Date& rDate, ExtDateFieldFormat 
eExtFormat,
-                                   const LocaleDataWrapper& rLocaleData, 
CalendarWrapper& rCalendarWrapper,
-                                   const Formatter::StaticFormatter* 
pStaticFormatter)
+                                   const LocaleDataWrapper& rLocaleData,
+                                   const Formatter::StaticFormatter& 
rStaticFormatter)
 {
     bool bShowCentury = false;
     switch (eExtFormat)
@@ -1439,22 +1439,16 @@ OUString DateFormatter::FormatDate(const Date& rDate, 
ExtDateFieldFormat eExtFor
     {
         case ExtDateFieldFormat::SystemLong:
         {
-            /* TODO: adapt all callers to pass a StaticFormatter. */
-            if (!pStaticFormatter)
-                return rLocaleData.getLongDate( rDate, rCalendarWrapper, 
!bShowCentury );
-            else
-            {
-                SvNumberFormatter* pFormatter = *pStaticFormatter;
-                const LanguageTag aFormatterLang( 
pFormatter->GetLanguageTag());
-                const sal_uInt32 nIndex = pFormatter->GetFormatIndex( 
NF_DATE_SYSTEM_LONG,
-                        rLocaleData.getLanguageTag().getLanguageType(false));
-                OUString aStr;
-                const Color* pCol;
-                pFormatter->GetOutputString( rDate - 
pFormatter->GetNullDate(), nIndex, aStr, &pCol);
-                // Reset to what other uses may expect.
-                pFormatter->ChangeIntl( aFormatterLang.getLanguageType(false));
-                return aStr;
-            }
+            SvNumberFormatter* pFormatter = rStaticFormatter;
+            const LanguageTag aFormatterLang( pFormatter->GetLanguageTag());
+            const sal_uInt32 nIndex = pFormatter->GetFormatIndex( 
NF_DATE_SYSTEM_LONG,
+                    rLocaleData.getLanguageTag().getLanguageType(false));
+            OUString aStr;
+            const Color* pCol;
+            pFormatter->GetOutputString( rDate - pFormatter->GetNullDate(), 
nIndex, aStr, &pCol);
+            // Reset to what other uses may expect.
+            pFormatter->ChangeIntl( aFormatterLang.getLanguageType(false));
+            return aStr;
         }
         case ExtDateFieldFormat::ShortDDMMYY:
         case ExtDateFieldFormat::ShortDDMMYYYY:
@@ -1499,8 +1493,7 @@ OUString DateFormatter::FormatDate(const Date& rDate, 
ExtDateFieldFormat eExtFor
 
 OUString DateFormatter::ImplGetDateAsText( const Date& rDate ) const
 {
-    return DateFormatter::FormatDate(rDate, GetExtDateFormat(), 
ImplGetLocaleDataWrapper(),
-            GetCalendarWrapper(), &maStaticFormatter);
+    return DateFormatter::FormatDate(rDate, GetExtDateFormat(), 
ImplGetLocaleDataWrapper(), maStaticFormatter);
 }
 
 static void ImplDateIncrementDay( Date& rDate, bool bUp )
@@ -2219,7 +2212,7 @@ namespace weld
     OUString DateFormatter::FormatNumber(int nValue) const
     {
         const LocaleDataWrapper& rLocaleData = 
Application::GetSettings().GetLocaleDataWrapper();
-        return ::DateFormatter::FormatDate(Date(nValue), m_eFormat, 
rLocaleData, GetCalendarWrapper());
+        return ::DateFormatter::FormatDate(Date(nValue), m_eFormat, 
rLocaleData, m_aStaticFormatter);
     }
 
     IMPL_LINK_NOARG(DateFormatter, FormatOutputHdl, LinkParamNone*, bool)
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to