calendarui/editors/src/KoreanLunarDateUtil.cpp
branchRCL_3
changeset 31 97232defd20e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/editors/src/KoreanLunarDateUtil.cpp	Tue Sep 14 21:17:03 2010 +0300
@@ -0,0 +1,228 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include "KoreanLunarDateUtil.h"
+// debug
+#include "calendarui_debug.h"
+
+const TInt KMaxLunarYear = 60;
+
+/**
+ * Public methods for constructing a CKoreanLunarDateUtil object.
+ */
+CKoreanLunarDateUtil* CKoreanLunarDateUtil::NewL(MCalenServices* aServices)
+    {
+    TRACE_ENTRY_POINT;
+    CKoreanLunarDateUtil* self = CKoreanLunarDateUtil::NewLC(aServices);
+    CleanupStack::Pop( self );
+    
+    TRACE_EXIT_POINT;
+    return self;
+    }
+
+CKoreanLunarDateUtil* CKoreanLunarDateUtil::NewLC(MCalenServices* aServices)
+    {
+    TRACE_ENTRY_POINT;
+    CKoreanLunarDateUtil* self = new (ELeave) CKoreanLunarDateUtil(aServices);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+CKoreanLunarDateUtil::CKoreanLunarDateUtil(MCalenServices* aServices):iServices(aServices)
+	{
+    TRACE_ENTRY_POINT;
+	}
+
+
+void CKoreanLunarDateUtil::ConstructL()
+	{
+    TRACE_ENTRY_POINT;
+    iConverter = CKoreanCalConv::NewL();
+	}
+
+CKoreanLunarDateUtil::~CKoreanLunarDateUtil()
+    {
+    TRACE_ENTRY_POINT;
+    delete iConverter;
+    }
+
+/**
+ * Method for getting nearest gregorian date from
+ * lunar day and month and gregorian reference.
+ */
+TDateTime CKoreanLunarDateUtil::GetNearestGregorianDateL( const TInt aMonth,
+                                                          const TInt aDay,
+                                                          const TBool aLeap,
+                                                          const TDateTime& aReference ) const
+	{
+    TRACE_ENTRY_POINT;
+    TKoreanDate refLunarDate;
+    TKoreanDate lunarDate;
+    TDateTime resDateTime;
+    TInt err = KErrNone;
+
+    iConverter->DateTimeToKoreanL( aReference, refLunarDate );
+    /* Try to convert with the year and cycle we got with the reference */
+    lunarDate.iCycle = refLunarDate.iCycle;
+    lunarDate.iYear = refLunarDate.iYear;
+    lunarDate.iMonth = aMonth;
+    lunarDate.iDay = aDay;
+    lunarDate.iLeapMonth = aLeap;
+    TRAP( err, iConverter->KoreanToDateTimeL( lunarDate, resDateTime ) );
+    if( err == KErrArgument )
+        { /* Date is invalid for this year (day 30 on a month
+             that has only 29 days on selected year or a leap month
+             not in this year), try to find suitable */
+        TKoreanDate lowerLimit;
+        TKoreanDate upperLimit;
+        iConverter->DateRange( lowerLimit, upperLimit );
+        while( 1 )
+            { /* Search by increasing year */
+            if( lunarDate.iYear < KMaxLunarYear )
+               {
+                lunarDate.iYear++;
+                }
+            else
+                {
+                lunarDate.iYear = 1;
+                lunarDate.iCycle++;
+                }
+            if( (lunarDate.iCycle == upperLimit.iCycle &&
+                 lunarDate.iYear > upperLimit.iYear)  ||
+                lunarDate.iCycle > upperLimit.iCycle )
+                { /* Could not find, just break */
+                break;
+                }
+            TRAP( err, iConverter->KoreanToDateTimeL( lunarDate, resDateTime ) );
+            if( err == KErrNone )
+                { /* Found suitable */
+                break;
+                }
+            }
+        if( err != KErrNone )
+            { /* Suitable not found by increasing,
+                 reset values and search by decreasing year */
+            lunarDate.iCycle = refLunarDate.iCycle;
+            lunarDate.iYear = refLunarDate.iYear;
+            lunarDate.iMonth = aMonth;
+            lunarDate.iDay = aDay;
+            while( 1 )
+                { /* Search by decreasing year */
+                if( lunarDate.iYear > 1 )
+                   {
+                    lunarDate.iYear--;
+                    }
+                else
+                    {
+                    if( lunarDate.iCycle == 0 )
+                        { /* Run out of cycles, break with error */
+                        break;
+                        }
+                    lunarDate.iYear = KMaxLunarYear;
+                    lunarDate.iCycle--;
+                    }
+                if( (lunarDate.iCycle == lowerLimit.iCycle &&
+                     lunarDate.iYear < lowerLimit.iYear)  ||
+                    lunarDate.iCycle < lowerLimit.iCycle )
+                    { /* Could not find, just break */
+                    break;
+                    }
+                TRAP( err, iConverter->KoreanToDateTimeL( lunarDate, resDateTime ) );
+                if( err == KErrNone )
+                    { /* Found suitable */
+                    break;
+                    }
+                }
+            }
+        }
+    /* If still not found, leave with error */
+    User::LeaveIfError( err );
+    
+    TRACE_ENTRY_POINT;
+    /* Otherwise return the result */
+    return resDateTime;
+	}
+
+/**
+* Method for getting lunar yearly repeats in gregorian dates.
+*/
+void CKoreanLunarDateUtil::GetLunarYearlyRepeatsL( RArray<TCalTime>& aRDates,
+                                                   const TDateTime& aEntryDate,
+                                                   const TBool aFloating ) const
+    {
+    TInt err = KErrNone;
+    TCalTime repeatDate;
+    TDateTime resDateTime;
+    TDateTime lowerLimit;
+    TKoreanDate upperKoreanLimit;
+    TKoreanDate lunarStartDate;
+    
+    /* Get the upper limit for dates in Korean lunar format */
+    iConverter->DateRange( lunarStartDate, upperKoreanLimit );
+    
+    /* Get the entry date in Korean lunar format */
+    iConverter->DateTimeToKoreanL( aEntryDate, lunarStartDate );
+    
+    /* Get the lower limit for dates in Gregorian format */
+    iConverter->DateRange( lowerLimit, resDateTime );
+    
+    /* Get the first occurrence of the event after
+    the lower limit in Korean lunar format */
+    iConverter->DateTimeToKoreanL(  GetNearestGregorianDateL( lunarStartDate.iMonth,
+                                  lunarStartDate.iDay,
+                                  lunarStartDate.iLeapMonth,
+                                  lowerLimit ),
+                                  lunarStartDate );
+    
+    while( 1 )
+        {
+        TRAP( err, iConverter->KoreanToDateTimeL( lunarStartDate, resDateTime ) );
+        if( err == KErrNone )
+            { /* Date exists in current year */
+            if( aFloating )
+                {
+                repeatDate.SetTimeLocalFloatingL( resDateTime );
+                }
+            else
+                {
+                repeatDate.SetTimeLocalL( resDateTime );
+                }
+            aRDates.AppendL( repeatDate );
+            }
+        /* Increase to next lunar year */
+        if( lunarStartDate.iYear < KMaxLunarYear )
+            {
+            lunarStartDate.iYear++;
+            }
+        else
+            {
+            lunarStartDate.iYear = 1;
+            lunarStartDate.iCycle++;
+            }
+        if( (lunarStartDate.iCycle == upperKoreanLimit.iCycle &&
+                lunarStartDate.iYear > upperKoreanLimit.iYear)  ||
+                lunarStartDate.iCycle > upperKoreanLimit.iCycle )
+            { /* Reached the limit, break */
+            break;
+            }
+        }
+    }
+    
+// End of file