LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - gregoimp.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 62 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             :  **********************************************************************
       5             :  * Copyright (c) 2003-2008, International Business Machines
       6             :  * Corporation and others.  All Rights Reserved.
       7             :  **********************************************************************
       8             :  * Author: Alan Liu
       9             :  * Created: September 2 2003
      10             :  * Since: ICU 2.8
      11             :  **********************************************************************
      12             :  */
      13             : 
      14             : #include "gregoimp.h"
      15             : 
      16             : #if !UCONFIG_NO_FORMATTING
      17             : 
      18             : #include "unicode/ucal.h"
      19             : #include "uresimp.h"
      20             : #include "cstring.h"
      21             : #include "uassert.h"
      22             : 
      23             : U_NAMESPACE_BEGIN
      24             : 
      25           0 : int32_t ClockMath::floorDivide(int32_t numerator, int32_t denominator) {
      26           0 :     return (numerator >= 0) ?
      27           0 :         numerator / denominator : ((numerator + 1) / denominator) - 1;
      28             : }
      29             : 
      30           0 : int32_t ClockMath::floorDivide(double numerator, int32_t denominator,
      31             :                           int32_t& remainder) {
      32             :     double quotient;
      33           0 :     quotient = uprv_floor(numerator / denominator);
      34           0 :     remainder = (int32_t) (numerator - (quotient * denominator));
      35           0 :     return (int32_t) quotient;
      36             : }
      37             : 
      38           0 : double ClockMath::floorDivide(double dividend, double divisor,
      39             :                          double& remainder) {
      40             :     // Only designed to work for positive divisors
      41           0 :     U_ASSERT(divisor > 0);
      42           0 :     double quotient = floorDivide(dividend, divisor);
      43           0 :     remainder = dividend - (quotient * divisor);
      44             :     // N.B. For certain large dividends, on certain platforms, there
      45             :     // is a bug such that the quotient is off by one.  If you doubt
      46             :     // this to be true, set a breakpoint below and run cintltst.
      47           0 :     if (remainder < 0 || remainder >= divisor) {
      48             :         // E.g. 6.7317038241449352e+022 / 86400000.0 is wrong on my
      49             :         // machine (too high by one).  4.1792057231752762e+024 /
      50             :         // 86400000.0 is wrong the other way (too low).
      51           0 :         double q = quotient;
      52           0 :         quotient += (remainder < 0) ? -1 : +1;
      53           0 :         if (q == quotient) {
      54             :             // For quotients > ~2^53, we won't be able to add or
      55             :             // subtract one, since the LSB of the mantissa will be >
      56             :             // 2^0; that is, the exponent (base 2) will be larger than
      57             :             // the length, in bits, of the mantissa.  In that case, we
      58             :             // can't give a correct answer, so we set the remainder to
      59             :             // zero.  This has the desired effect of making extreme
      60             :             // values give back an approximate answer rather than
      61             :             // crashing.  For example, UDate values above a ~10^25
      62             :             // might all have a time of midnight.
      63           0 :             remainder = 0;
      64             :         } else {
      65           0 :             remainder = dividend - (quotient * divisor);
      66             :         }
      67             :     }
      68           0 :     U_ASSERT(0 <= remainder && remainder < divisor);
      69           0 :     return quotient;
      70             : }
      71             : 
      72             : const int32_t JULIAN_1_CE    = 1721426; // January 1, 1 CE Gregorian
      73             : const int32_t JULIAN_1970_CE = 2440588; // January 1, 1970 CE Gregorian
      74             : 
      75             : const int16_t Grego::DAYS_BEFORE[24] =
      76             :     {0,31,59,90,120,151,181,212,243,273,304,334,
      77             :      0,31,60,91,121,152,182,213,244,274,305,335};
      78             : 
      79             : const int8_t Grego::MONTH_LENGTH[24] =
      80             :     {31,28,31,30,31,30,31,31,30,31,30,31,
      81             :      31,29,31,30,31,30,31,31,30,31,30,31};
      82             : 
      83           0 : double Grego::fieldsToDay(int32_t year, int32_t month, int32_t dom) {
      84             : 
      85           0 :     int32_t y = year - 1;
      86             : 
      87           0 :     double julian = 365 * y + ClockMath::floorDivide(y, 4) + (JULIAN_1_CE - 3) + // Julian cal
      88           0 :         ClockMath::floorDivide(y, 400) - ClockMath::floorDivide(y, 100) + 2 + // => Gregorian cal
      89           0 :         DAYS_BEFORE[month + (isLeapYear(year) ? 12 : 0)] + dom; // => month/dom
      90             : 
      91           0 :     return julian - JULIAN_1970_CE; // JD => epoch day
      92             : }
      93             : 
      94           0 : void Grego::dayToFields(double day, int32_t& year, int32_t& month,
      95             :                         int32_t& dom, int32_t& dow, int32_t& doy) {
      96             : 
      97             :     // Convert from 1970 CE epoch to 1 CE epoch (Gregorian calendar)
      98           0 :     day += JULIAN_1970_CE - JULIAN_1_CE;
      99             : 
     100             :     // Convert from the day number to the multiple radix
     101             :     // representation.  We use 400-year, 100-year, and 4-year cycles.
     102             :     // For example, the 4-year cycle has 4 years + 1 leap day; giving
     103             :     // 1461 == 365*4 + 1 days.
     104           0 :     int32_t n400 = ClockMath::floorDivide(day, 146097, doy); // 400-year cycle length
     105           0 :     int32_t n100 = ClockMath::floorDivide(doy, 36524, doy); // 100-year cycle length
     106           0 :     int32_t n4   = ClockMath::floorDivide(doy, 1461, doy); // 4-year cycle length
     107           0 :     int32_t n1   = ClockMath::floorDivide(doy, 365, doy);
     108           0 :     year = 400*n400 + 100*n100 + 4*n4 + n1;
     109           0 :     if (n100 == 4 || n1 == 4) {
     110           0 :         doy = 365; // Dec 31 at end of 4- or 400-year cycle
     111             :     } else {
     112           0 :         ++year;
     113             :     }
     114             :     
     115           0 :     UBool isLeap = isLeapYear(year);
     116             :     
     117             :     // Gregorian day zero is a Monday.
     118           0 :     dow = (int32_t) uprv_fmod(day + 1, 7);
     119           0 :     dow += (dow < 0) ? (UCAL_SUNDAY + 7) : UCAL_SUNDAY;
     120             : 
     121             :     // Common Julian/Gregorian calculation
     122           0 :     int32_t correction = 0;
     123           0 :     int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
     124           0 :     if (doy >= march1) {
     125           0 :         correction = isLeap ? 1 : 2;
     126             :     }
     127           0 :     month = (12 * (doy + correction) + 6) / 367; // zero-based month
     128           0 :     dom = doy - DAYS_BEFORE[month + (isLeap ? 12 : 0)] + 1; // one-based DOM
     129           0 :     doy++; // one-based doy
     130           0 : }
     131             : 
     132           0 : void Grego::timeToFields(UDate time, int32_t& year, int32_t& month,
     133             :                         int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid) {
     134             :     double millisInDay;
     135           0 :     double day = ClockMath::floorDivide((double)time, (double)U_MILLIS_PER_DAY, millisInDay);
     136           0 :     mid = (int32_t)millisInDay;
     137           0 :     dayToFields(day, year, month, dom, dow, doy);
     138           0 : }
     139             : 
     140           0 : int32_t Grego::dayOfWeek(double day) {
     141             :     int32_t dow;
     142           0 :     ClockMath::floorDivide(day + UCAL_THURSDAY, 7, dow);
     143           0 :     return (dow == 0) ? UCAL_SATURDAY : dow;
     144             : }
     145             : 
     146           0 : int32_t Grego::dayOfWeekInMonth(int32_t year, int32_t month, int32_t dom) {
     147           0 :     int32_t weekInMonth = (dom + 6)/7;
     148           0 :     if (weekInMonth == 4) {
     149           0 :         if (dom + 7 > monthLength(year, month)) {
     150           0 :             weekInMonth = -1;
     151             :         }
     152           0 :     } else if (weekInMonth == 5) {
     153           0 :         weekInMonth = -1;
     154             :     }
     155           0 :     return weekInMonth;
     156             : }
     157             : 
     158             : U_NAMESPACE_END
     159             : 
     160             : #endif
     161             : //eof

Generated by: LCOV version 1.13