summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--i18npool/inc/calendar_gregorian.hxx3
-rw-r--r--i18npool/source/calendar/calendar_gregorian.cxx247
2 files changed, 4 insertions, 246 deletions
diff --git a/i18npool/inc/calendar_gregorian.hxx b/i18npool/inc/calendar_gregorian.hxx
index 4a16c00c3eb6..283e1b7c60e9 100644
--- a/i18npool/inc/calendar_gregorian.hxx
+++ b/i18npool/inc/calendar_gregorian.hxx
@@ -116,9 +116,6 @@ private:
/** Submit fieldSetValue array according to fieldSet. */
void submitFields() throw(css::uno::RuntimeException);
- /** Submit fieldSetValue array according to fieldSet, plus EYMDhms if >=0,
- plus zone and DST if != 0 */
- void submitValues( sal_Int32 nEra, sal_Int32 nYear, sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute, sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST) throw(css::uno::RuntimeException);
/** Set fields internally. */
void setValue() throw(css::uno::RuntimeException);
/** Obtain combined field values for timezone offset (minutes+secondmillis)
diff --git a/i18npool/source/calendar/calendar_gregorian.cxx b/i18npool/source/calendar/calendar_gregorian.cxx
index 275b24dff0ed..f3fa8ea6dac8 100644
--- a/i18npool/source/calendar/calendar_gregorian.cxx
+++ b/i18npool/source/calendar/calendar_gregorian.cxx
@@ -491,260 +491,21 @@ void Calendar_gregorian::submitFields() throw(css::uno::RuntimeException)
body->set( fieldNameConverter( CalendarFieldIndex::DST_OFFSET), nDSTOffset);
}
-void Calendar_gregorian::submitValues( sal_Int32 nEra, sal_Int32 nYear,
- sal_Int32 nMonth, sal_Int32 nDay, sal_Int32 nHour, sal_Int32 nMinute,
- sal_Int32 nSecond, sal_Int32 nMilliSecond, sal_Int32 nZone, sal_Int32 nDST )
- throw(css::uno::RuntimeException)
-{
- submitFields();
- if (nEra >= 0)
- body->set( UCAL_ERA, nEra);
- if (nYear >= 0)
- body->set( UCAL_YEAR, nYear);
- if (nMonth >= 0)
- body->set( UCAL_MONTH, nMonth);
- if (nDay >= 0)
- body->set( UCAL_DATE, nDay);
- if (nHour >= 0)
- body->set( UCAL_HOUR_OF_DAY, nHour);
- if (nMinute >= 0)
- body->set( UCAL_MINUTE, nMinute);
- if (nSecond >= 0)
- body->set( UCAL_SECOND, nSecond);
- if (nMilliSecond >= 0)
- body->set( UCAL_MILLISECOND, nMilliSecond);
- if (nZone != 0)
- body->set( UCAL_ZONE_OFFSET, nZone);
- if (nDST != 0)
- body->set( UCAL_DST_OFFSET, nDST);
-}
-
-static void lcl_setCombinedOffsetFieldValues( sal_Int32 nValue,
- sal_Int16 rFieldSetValue[], sal_Int16 rFieldValue[],
- sal_Int16 nParentFieldIndex, sal_Int16 nChildFieldIndex )
-{
- sal_Int32 nTrunc = nValue / 60000;
- rFieldSetValue[nParentFieldIndex] = rFieldValue[nParentFieldIndex] =
- static_cast<sal_Int16>( nTrunc);
- sal_uInt16 nMillis = static_cast<sal_uInt16>( abs( nValue - nTrunc * 60000));
- rFieldSetValue[nChildFieldIndex] = rFieldValue[nChildFieldIndex] =
- static_cast<sal_Int16>( nMillis);
-}
-
void Calendar_gregorian::setValue() throw(RuntimeException)
{
- // Correct DST glitch, see also localtime/gmtime conversion pitfalls at
- // http://www.erack.de/download/timetest.c
-
- // #i24082# in order to make the DST correction work in all
- // circumstances, the time values have to be always resubmitted,
- // regardless whether specified by the caller or not. It is not
- // sufficient to rely on the ICU internal values previously set, as the
- // following may happen:
- // - Let 2004-03-28T02:00 be the onsetRule.
- // - On 2004-03-29 (calendar initialized with 2004-03-29T00:00 DST) set
- // a date of 2004-03-28 => calendar results in 2004-03-27T23:00 no DST.
- // - Correcting this with simply "2004-03-28 no DST" and no time
- // specified results in 2004-03-29T00:00, the ICU internal 23:00 time
- // being adjusted to 24:00 in this case, switching one day further.
- // => submit 2004-03-28T00:00 no DST.
-
- // This got even weirder since ICU incorporated also historical data,
- // even the timezone may differ for different dates! It is necessary to
- // let ICU choose the corresponding OlsonTimeZone transitions and adapt
- // values.
- // #i86094# gives examples where that went wrong:
- // TZ=Europe/Moscow date <= 1919-07-01
- // zone +2:30:48 (!) instead of +3h, DST +2h instead of +1h
- // TZ=America/St_Johns date <= 1935-03-30
- // zone -3:30:52 (!) instead of -3:30
-
// Copy fields before calling submitFields() directly or indirectly below.
memcpy(fieldSetValue, fieldValue, sizeof(fieldSetValue));
// Possibly setup ERA and YEAR in fieldSetValue.
mapToGregorian();
- DUMP_ICU_CAL_MSG(("%s\n","setValue() before any submission"));
- DUMP_I18N_CAL_MSG(("%s\n","setValue() before any submission"));
-
- bool bNeedZone = !(fieldSet & (1 << CalendarFieldIndex::ZONE_OFFSET));
- bool bNeedDST = !(fieldSet & (1 << CalendarFieldIndex::DST_OFFSET));
- sal_Int32 nZone1, nDST1, nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0;
- nZone1 = nDST1 = nZone0 = nDST0 = 0;
- nEra = nYear = nMonth = nDay = nHour = nMinute = nSecond = nMilliSecond = -1;
- if ( bNeedZone || bNeedDST )
- {
- UErrorCode status;
- if ( !(fieldSet & (1 << CalendarFieldIndex::ERA)) )
- {
- nEra = body->get( UCAL_ERA, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nEra = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::YEAR)) )
- {
- nYear = body->get( UCAL_YEAR, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nYear = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::MONTH)) )
- {
- nMonth = body->get( UCAL_MONTH, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nMonth = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::DAY_OF_MONTH)) )
- {
- nDay = body->get( UCAL_DATE, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nDay = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::HOUR)) )
- {
- nHour = body->get( UCAL_HOUR_OF_DAY, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nHour = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::MINUTE)) )
- {
- nMinute = body->get( UCAL_MINUTE, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nMinute = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::SECOND)) )
- {
- nSecond = body->get( UCAL_SECOND, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nSecond = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::MILLISECOND)) )
- {
- nMilliSecond = body->get( UCAL_MILLISECOND, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nMilliSecond = -1;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::ZONE_OFFSET)) )
- {
- nZone0 = body->get( UCAL_ZONE_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nZone0 = 0;
- }
- if ( !(fieldSet & (1 << CalendarFieldIndex::DST_OFFSET)) )
- {
- nDST0 = body->get( UCAL_DST_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nDST0 = 0;
- }
-
- // Submit values to obtain a time zone and DST corresponding to the date/time.
- submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone0, nDST0);
-
- DUMP_ICU_CAL_MSG(("%s\n","setValue() in bNeedZone||bNeedDST after submitValues()"));
- DUMP_I18N_CAL_MSG(("%s\n","setValue() in bNeedZone||bNeedDST after submitValues()"));
- nZone1 = body->get( UCAL_ZONE_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nZone1 = 0;
- nDST1 = body->get( UCAL_DST_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nDST1 = 0;
- }
+ DUMP_ICU_CAL_MSG(("%s\n","setValue() before submission"));
+ DUMP_I18N_CAL_MSG(("%s\n","setValue() before submission"));
- // The original submission, may lead to a different zone/DST and
- // different date.
submitFields();
- DUMP_ICU_CAL_MSG(("%s\n","setValue() after original submission"));
- DUMP_I18N_CAL_MSG(("%s\n","setValue() after original submission"));
- if ( bNeedZone || bNeedDST )
- {
- UErrorCode status;
- sal_Int32 nZone2 = body->get( UCAL_ZONE_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nZone2 = nZone1;
- sal_Int32 nDST2 = body->get( UCAL_DST_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nDST2 = nDST1;
- if ( nZone0 != nZone1 || nZone2 != nZone1 || nDST0 != nDST1 || nDST2 != nDST1 )
- {
- // Due to different DSTs, resulting date values may differ if
- // DST is onset at 00:00 and the very onsetRule date was
- // submitted with DST off => date-1 23:00, for example, which
- // is not what we want.
- // Resubmit all values, this time including DST => date 01:00
- // Similar for zone differences.
- // If already the first full submission with nZone0 and nDST0
- // lead to date-1 23:00, the original submission was based on
- // that date if it wasn't a full date (nDST0 set, nDST1 not
- // set, nDST2==nDST1). If it was January 1st without year we're
- // even off by one year now. Resubmit all values including new
- // DST => date 00:00.
-
- // Set field values accordingly in case they were used.
- if (!bNeedZone)
- lcl_setCombinedOffsetFieldValues( nZone2, fieldSetValue,
- fieldValue, CalendarFieldIndex::ZONE_OFFSET,
- CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS);
- if (!bNeedDST)
- lcl_setCombinedOffsetFieldValues( nDST2, fieldSetValue,
- fieldValue, CalendarFieldIndex::DST_OFFSET,
- CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS);
- submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone2, nDST2);
- DUMP_ICU_CAL_MSG(("%s\n","setValue() after Zone/DST glitch resubmit"));
- DUMP_I18N_CAL_MSG(("%s\n","setValue() after Zone/DST glitch resubmit"));
-
- // Time zone transition => resubmit.
- // TZ=America/St_Johns date <= 1935-03-30
- // -3:30:52 (!) instead of -3:30
- // if first submission included time zone -3:30 that would be wrong.
- bool bResubmit = false;
- sal_Int32 nZone3 = body->get( UCAL_ZONE_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nZone3 = nZone2;
- if (nZone3 != nZone2)
- {
- bResubmit = true;
- if (!bNeedZone)
- lcl_setCombinedOffsetFieldValues( nZone3, fieldSetValue,
- fieldValue, CalendarFieldIndex::ZONE_OFFSET,
- CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS);
- }
+ DUMP_ICU_CAL_MSG(("%s\n","setValue() after submission"));
+ DUMP_I18N_CAL_MSG(("%s\n","setValue() after submission"));
- // If the DST onset rule says to switch from 00:00 to 01:00 and
- // we tried to set onsetDay 00:00 with DST, the result was
- // onsetDay-1 23:00 and no DST, which is not what we want. So
- // once again without DST, resulting in onsetDay 01:00 and DST.
- // Yes, this seems to be weird, but logically correct.
- // It doesn't even have to be on an onsetDay as the DST is
- // factored in all days by ICU and there seems to be some
- // unknown behavior.
- // TZ=Asia/Tehran 1999-03-22 exposes this, for example.
- sal_Int32 nDST3 = body->get( UCAL_DST_OFFSET, status = U_ZERO_ERROR);
- if ( !U_SUCCESS(status) )
- nDST3 = nDST2;
- if (nDST2 != nDST3 && !nDST3)
- {
- bResubmit = true;
- if (!bNeedDST)
- {
- fieldSetValue[CalendarFieldIndex::DST_OFFSET] =
- fieldValue[CalendarFieldIndex::DST_OFFSET] = 0;
- fieldSetValue[CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS] =
- fieldValue[CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS] = 0;
- }
- }
- if (bResubmit)
- {
- submitValues( nEra, nYear, nMonth, nDay, nHour, nMinute, nSecond, nMilliSecond, nZone3, nDST3);
- DUMP_ICU_CAL_MSG(("%s\n","setValue() after Zone/DST glitch 2nd resubmit"));
- DUMP_I18N_CAL_MSG(("%s\n","setValue() after Zone/DST glitch 2nd resubmit"));
- }
- SAL_INFO( "i18npool", "Calendar_gregorian::setValue:"
- " nZone0 " << nZone0 << ", nDST0 " << nDST0 <<
- ", nZone1 " << nZone1 << ", nDST1 " << nDST1 <<
- ", nZone2 " << nZone2 << ", nDST2 " << nDST2 <<
- ", nZone3 " << nZone3 << ", nDST3 " << nDST3);
- }
- }
#if erDUMP_ICU_CALENDAR || erDUMP_I18N_CALENDAR
{
// force icu::Calendar to recalculate