LCOV - code coverage report
Current view: top level - i18npool/source/calendar - calendar_hijri.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 118 0.0 %
Date: 2012-08-25 Functions: 0 8 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 44 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : 
      21                 :            : #include <stdlib.h>
      22                 :            : #include <math.h>
      23                 :            : 
      24                 :            : #include "calendar_hijri.hxx"
      25                 :            : 
      26                 :            : using namespace ::com::sun::star::uno;
      27                 :            : using namespace ::com::sun::star::lang;
      28                 :            : 
      29                 :            : #define ERROR RuntimeException()
      30                 :            : 
      31                 :            : #define GREGORIAN_CROSSOVER 2299161
      32                 :            : 
      33                 :            : namespace com { namespace sun { namespace star { namespace i18n {
      34                 :            : 
      35                 :            : // not used
      36                 :            : //static UErrorCode status; // status is shared in all calls to Calendar, it has to be reset for each call.
      37                 :            : 
      38                 :            : // radians per degree (pi/180)
      39                 :            : const double Calendar_hijri::RadPerDeg      = 0.01745329251994329577;
      40                 :            : 
      41                 :            : // Synodic Period (mean time between 2 successive new moon: 29d, 12 hr, 44min, 3sec
      42                 :            : const double Calendar_hijri::SynPeriod      = 29.53058868;
      43                 :            : const double Calendar_hijri::SynMonth       = 365.25/29.53058868;   // Solar days in a year/SynPeriod
      44                 :            : 
      45                 :            : // Julian day on Jan 1, 1900
      46                 :            : const double Calendar_hijri::jd1900     = 2415020.75933;
      47                 :            : 
      48                 :            : // Reference point: March 26, 2001 == 1422 Hijri == 1252 Synodial month from 1900
      49                 :            : const sal_Int32 Calendar_hijri::SynRef      = 1252;
      50                 :            : const sal_Int32 Calendar_hijri::GregRef     = 1422;
      51                 :            : 
      52                 :            : // Local time specific to Saudi Arabia
      53                 :            : const double Calendar_hijri::SA_TimeZone    = 3.0;
      54                 :            : 
      55                 :            : const double Calendar_hijri::EveningPeriod  = 6.0;
      56                 :            : 
      57                 :            : const sal_Int32 Calendar_hijri::LeapYear[] = {
      58                 :            :     2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29
      59                 :            : };
      60                 :            : 
      61                 :          0 : Calendar_hijri::Calendar_hijri()
      62                 :            : {
      63                 :          0 :     cCalendar = "com.sun.star.i18n.Calendar_hijri";
      64                 :          0 : }
      65                 :            : 
      66                 :            : #define FIELDS  ((1 << CalendarFieldIndex::ERA) | (1 << CalendarFieldIndex::YEAR) | (1 << CalendarFieldIndex::MONTH) | (1 << CalendarFieldIndex::DAY_OF_MONTH))
      67                 :            : 
      68                 :            : // map field value from hijri calendar to gregorian calendar
      69                 :          0 : void Calendar_hijri::mapToGregorian() throw(RuntimeException)
      70                 :            : {
      71         [ #  # ]:          0 :     if (fieldSet & FIELDS) {
      72                 :          0 :         sal_Int32 day = (sal_Int32)fieldSetValue[CalendarFieldIndex::DAY_OF_MONTH];
      73                 :          0 :         sal_Int32 month = (sal_Int32)fieldSetValue[CalendarFieldIndex::MONTH] + 1;
      74                 :          0 :         sal_Int32 year = (sal_Int32)fieldSetValue[CalendarFieldIndex::YEAR];
      75         [ #  # ]:          0 :         if (fieldSetValue[CalendarFieldIndex::ERA] == 0)
      76                 :          0 :         year *= -1;
      77                 :            : 
      78         [ #  # ]:          0 :         ToGregorian(&day, &month, &year);
      79                 :            : 
      80                 :          0 :         fieldSetValue[CalendarFieldIndex::ERA] = year <= 0 ? 0 : 1;
      81                 :          0 :         fieldSetValue[CalendarFieldIndex::MONTH] = sal::static_int_cast<sal_Int16>(month - 1);
      82                 :          0 :         fieldSetValue[CalendarFieldIndex::DAY_OF_MONTH] = (sal_Int16) day;
      83                 :          0 :         fieldSetValue[CalendarFieldIndex::YEAR] = (sal_Int16) abs(year);
      84                 :          0 :         fieldSet |= FIELDS;
      85                 :            :     }
      86                 :          0 : }
      87                 :            : 
      88                 :            : // map field value from gregorian calendar to hijri calendar
      89                 :          0 : void Calendar_hijri::mapFromGregorian() throw(RuntimeException)
      90                 :            : {
      91                 :            :     sal_Int32 month, day, year;
      92                 :            : 
      93                 :          0 :     day = (sal_Int32)fieldValue[CalendarFieldIndex::DAY_OF_MONTH];
      94                 :          0 :     month = (sal_Int32)fieldValue[CalendarFieldIndex::MONTH] + 1;
      95                 :          0 :     year = (sal_Int32)fieldValue[CalendarFieldIndex::YEAR];
      96         [ #  # ]:          0 :     if (fieldValue[CalendarFieldIndex::ERA] == 0)
      97                 :          0 :         year *= -1;
      98                 :            : 
      99                 :            :     // Get Hijri date
     100         [ #  # ]:          0 :     getHijri(&day, &month, &year);
     101                 :            : 
     102                 :          0 :     fieldValue[CalendarFieldIndex::DAY_OF_MONTH] = (sal_Int16)day;
     103                 :          0 :     fieldValue[CalendarFieldIndex::MONTH] = sal::static_int_cast<sal_Int16>(month - 1);
     104                 :          0 :     fieldValue[CalendarFieldIndex::YEAR] = (sal_Int16) abs(year);
     105                 :          0 :     fieldValue[CalendarFieldIndex::ERA] = (sal_Int16) year < 1 ? 0 : 1;
     106                 :          0 : }
     107                 :            : 
     108                 :            : //
     109                 :            : // This function returns the Julian date/time of the Nth new moon since
     110                 :            : // January 1900.  The synodic month is passed as parameter.
     111                 :            : //
     112                 :            : // Adapted from "Astronomical  Formulae for Calculators" by
     113                 :            : // Jean Meeus, Third Edition, Willmann-Bell, 1985.
     114                 :            : //
     115                 :            : double
     116                 :          0 : Calendar_hijri::NewMoon(sal_Int32 n)
     117                 :            : {
     118                 :            :     double jd, t, t2, t3, k, ma, sa, tf, xtra;
     119                 :          0 :     k = n;
     120                 :          0 :     t = k/1236.85;  // Time in Julian centuries from 1900 January 0.5
     121                 :          0 :     t2 = t * t;
     122                 :          0 :     t3 = t2 * t;
     123                 :            : 
     124                 :            :     // Mean time of phase
     125                 :            :     jd =  jd1900
     126                 :            :         + SynPeriod * k
     127                 :            :         - 0.0001178 * t2
     128                 :            :         - 0.000000155 * t3
     129                 :          0 :         + 0.00033 * sin(RadPerDeg * (166.56 + 132.87 * t - 0.009173 * t2));
     130                 :            : 
     131                 :            :     // Sun's mean anomaly in radian
     132                 :            :     sa =  RadPerDeg * (359.2242
     133                 :            :                 + 29.10535608 * k
     134                 :            :                 - 0.0000333 * t2
     135                 :          0 :                 - 0.00000347 * t3);
     136                 :            : 
     137                 :            :     // Moon's mean anomaly
     138                 :            :     ma =  RadPerDeg * (306.0253
     139                 :            :                 + 385.81691806 * k
     140                 :            :                 + 0.0107306 * t2
     141                 :          0 :                 + 0.00001236 * t3);
     142                 :            : 
     143                 :            :     // Moon's argument of latitude
     144                 :            :     tf = RadPerDeg * 2.0 * (21.2964
     145                 :            :                 + 390.67050646 * k
     146                 :            :                 - 0.0016528 * t2
     147                 :          0 :                 - 0.00000239 * t3);
     148                 :            : 
     149                 :            :     // should reduce to interval between 0 to 1.0 before calculating further
     150                 :            :     // Corrections for New Moon
     151                 :          0 :     xtra = (0.1734 - 0.000393 * t) * sin(sa)
     152                 :          0 :         + 0.0021 * sin(sa * 2)
     153                 :          0 :         - 0.4068 * sin(ma)
     154                 :          0 :         + 0.0161 * sin(2 * ma)
     155                 :          0 :         - 0.0004 * sin(3 * ma)
     156                 :          0 :         + 0.0104 * sin(tf)
     157                 :          0 :         - 0.0051 * sin(sa + ma)
     158                 :          0 :         - 0.0074 * sin(sa - ma)
     159                 :          0 :         + 0.0004 * sin(tf + sa)
     160                 :          0 :         - 0.0004 * sin(tf - sa)
     161                 :          0 :         - 0.0006 * sin(tf + ma)
     162                 :          0 :         + 0.0010 * sin(tf - ma)
     163                 :          0 :         + 0.0005 * sin(sa + 2 * ma);
     164                 :            : 
     165                 :            :     // convert from Ephemeris Time (ET) to (approximate) Universal Time (UT)
     166                 :          0 :     jd += xtra - (0.41 + 1.2053 * t + 0.4992 * t2)/1440;
     167                 :            : 
     168                 :          0 :     return (jd);
     169                 :            : }
     170                 :            : 
     171                 :            : // Get Hijri Date
     172                 :            : void
     173                 :          0 : Calendar_hijri::getHijri(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
     174                 :            : {
     175                 :            :     double prevday;
     176                 :            : //  double dayfraction;
     177                 :            :     sal_Int32 syndiff;
     178                 :            :     sal_Int32 newsyn;
     179                 :            :     double newjd;
     180                 :            :     double julday;
     181                 :            :     sal_Int32 synmonth;
     182                 :            : 
     183                 :            :     // Get Julian Day from Gregorian
     184                 :          0 :     julday = getJulianDay(*day, *month, *year);
     185                 :            : 
     186                 :            :     // obtain approx. of how many Synodic months since the beginning of the year 1900
     187                 :          0 :     synmonth = (sal_Int32)(0.5 + (julday - jd1900)/SynPeriod);
     188                 :            : 
     189                 :          0 :     newsyn = synmonth;
     190                 :          0 :     prevday = (sal_Int32)julday - 0.5;
     191                 :            : 
     192         [ #  # ]:          0 :     do {
     193                 :          0 :         newjd = NewMoon(newsyn);
     194                 :            : 
     195                 :            :         // Decrement syndonic months
     196                 :          0 :         newsyn--;
     197                 :            :     } while (newjd > prevday);
     198                 :          0 :     newsyn++;
     199                 :            : 
     200                 :            :     // difference from reference point
     201                 :          0 :     syndiff = newsyn - SynRef;
     202                 :            : 
     203                 :            :     // Round up the day
     204                 :          0 :     *day = (sal_Int32)(((sal_Int32)julday) - newjd + 0.5);
     205                 :          0 :     *month =  (syndiff % 12) + 1;
     206                 :            : 
     207                 :            :     // currently not supported
     208                 :            :     //dayOfYear = (sal_Int32)(month * SynPeriod + day);
     209                 :          0 :     *year = GregRef + (sal_Int32)(syndiff / 12);
     210                 :            : 
     211                 :            :     // If month negative, consider it previous year
     212 [ #  # ][ #  # ]:          0 :     if (syndiff != 0 && *month <= 0) {
     213                 :          0 :         *month += 12;
     214                 :          0 :         (*year)--;
     215                 :            :     }
     216                 :            : 
     217                 :            :     // If Before Hijri subtract 1
     218         [ #  # ]:          0 :     if (*year <= 0) (*year)--;
     219                 :          0 : }
     220                 :            : 
     221                 :            : void
     222                 :          0 : Calendar_hijri::ToGregorian(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
     223                 :            : {
     224                 :            :     sal_Int32 nmonth;
     225                 :            : //    double dayfraction;
     226                 :            :     double jday;
     227                 :            : //    sal_Int32 dayint;
     228                 :            : 
     229         [ #  # ]:          0 :     if ( *year < 0 ) (*year)++;
     230                 :            : 
     231                 :            :     // Number of month from reference point
     232                 :          0 :     nmonth = *month + *year * 12 - (GregRef * 12 + 1);
     233                 :            : 
     234                 :            :     // Add Synodic Reference point
     235                 :          0 :     nmonth += SynRef;
     236                 :            : 
     237                 :            :     // Get Julian days add time too
     238                 :          0 :     jday = NewMoon(nmonth) + *day;
     239                 :            : 
     240                 :            :     // Round-up
     241                 :          0 :     jday = (double)((sal_Int32)(jday + 0.5));
     242                 :            : 
     243                 :            :     // Use algorithm from "Numerical Recipes in C"
     244                 :          0 :     getGregorianDay((sal_Int32)jday, day, month, year);
     245                 :            : 
     246                 :            :     // Julian -> Gregorian only works for non-negative year
     247         [ #  # ]:          0 :     if ( *year <= 0 ) {
     248                 :          0 :     *day = -1;
     249                 :          0 :     *month = -1;
     250                 :          0 :     *year = -1;
     251                 :            :     }
     252                 :          0 : }
     253                 :            : 
     254                 :            : /* this algorithm is taken from "Numerical Recipes in C", 2nd ed, pp 14-15. */
     255                 :            : /* this algorithm only valid for non-negative gregorian year                */
     256                 :            : void
     257                 :          0 : Calendar_hijri::getGregorianDay(sal_Int32 lJulianDay, sal_Int32 *pnDay, sal_Int32 *pnMonth, sal_Int32 *pnYear)
     258                 :            : {
     259                 :            :     /* working variables */
     260                 :            :     long lFactorA, lFactorB, lFactorC, lFactorD, lFactorE;
     261                 :            : 
     262                 :            :     /* test whether to adjust for the Gregorian calendar crossover */
     263         [ #  # ]:          0 :     if (lJulianDay >= GREGORIAN_CROSSOVER) {
     264                 :            :     /* calculate a small adjustment */
     265                 :          0 :     long lAdjust = (long) (((float) (lJulianDay - 1867216) - 0.25) / 36524.25);
     266                 :            : 
     267                 :          0 :     lFactorA = lJulianDay + 1 + lAdjust - ((long) (0.25 * lAdjust));
     268                 :            : 
     269                 :            :     } else {
     270                 :            :     /* no adjustment needed */
     271                 :          0 :     lFactorA = lJulianDay;
     272                 :            :     }
     273                 :            : 
     274                 :          0 :     lFactorB = lFactorA + 1524;
     275                 :          0 :     lFactorC = (long) (6680.0 + ((float) (lFactorB - 2439870) - 122.1) / 365.25);
     276                 :          0 :     lFactorD = (long) (365 * lFactorC + (0.25 * lFactorC));
     277                 :          0 :     lFactorE = (long) ((lFactorB - lFactorD) / 30.6001);
     278                 :            : 
     279                 :            :     /* now, pull out the day number */
     280                 :          0 :     *pnDay = lFactorB - lFactorD - (long) (30.6001 * lFactorE);
     281                 :            : 
     282                 :            :     /* ...and the month, adjusting it if necessary */
     283                 :          0 :     *pnMonth = lFactorE - 1;
     284         [ #  # ]:          0 :     if (*pnMonth > 12)
     285                 :          0 :     (*pnMonth) -= 12;
     286                 :            : 
     287                 :            :     /* ...and similarly for the year */
     288                 :          0 :     *pnYear = lFactorC - 4715;
     289         [ #  # ]:          0 :     if (*pnMonth > 2)
     290                 :          0 :     (*pnYear)--;
     291                 :            : 
     292                 :            : // Negative year adjustments
     293         [ #  # ]:          0 :     if (*pnYear <= 0)
     294                 :          0 :     (*pnYear)--;
     295                 :          0 : }
     296                 :            : 
     297                 :            : double
     298                 :          0 : Calendar_hijri::getJulianDay(sal_Int32 day, sal_Int32 month, sal_Int32 year)
     299                 :            : {
     300                 :            :     double jy, jm;
     301                 :            : 
     302         [ #  # ]:          0 :     if( year == 0 ) {
     303                 :          0 :     return -1.0;
     304                 :            :     }
     305                 :            : 
     306 [ #  # ][ #  # ]:          0 :     if( year == 1582 && month == 10 && day > 4 && day < 15 ) {
         [ #  # ][ #  # ]
     307                 :          0 :     return -1.0;
     308                 :            :     }
     309                 :            : 
     310         [ #  # ]:          0 :     if( month > 2 ) {
     311                 :          0 :     jy = year;
     312                 :          0 :     jm = month + 1;
     313                 :            :     } else {
     314                 :          0 :     jy = year - 1;
     315                 :          0 :     jm = month + 13;
     316                 :            :     }
     317                 :            : 
     318                 :          0 :     sal_Int32 intgr = (sal_Int32)((sal_Int32)(365.25 * jy) + (sal_Int32)(30.6001 * jm) + day + 1720995 );
     319                 :            : 
     320                 :            :     //check for switch to Gregorian calendar
     321                 :          0 :     double gregcal = 15 + 31 * ( 10 + 12 * 1582 );
     322                 :            : 
     323         [ #  # ]:          0 :     if( day + 31 * (month + 12 * year) >= gregcal ) {
     324                 :            :     double ja;
     325                 :          0 :     ja = (sal_Int32)(0.01 * jy);
     326                 :          0 :     intgr += (sal_Int32)(2 - ja + (sal_Int32)(0.25 * ja));
     327                 :            :     }
     328                 :            : 
     329                 :          0 :     return (double) intgr;
     330                 :            : }
     331                 :            : 
     332                 :            : }}}}
     333                 :            : 
     334                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10