1/*
2*******************************************************************************
3* Copyright (C) 2003 - 2009, International Business Machines Corporation and  *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*/
7
8#include "unicode/utypes.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12#include "umutex.h"
13#include "coptccal.h"
14#include "cecal.h"
15#include <float.h>
16
17U_NAMESPACE_BEGIN
18
19UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CopticCalendar)
20
21static const int32_t COPTIC_JD_EPOCH_OFFSET  = 1824665;
22
23//-------------------------------------------------------------------------
24// Constructors...
25//-------------------------------------------------------------------------
26
27CopticCalendar::CopticCalendar(const Locale& aLocale, UErrorCode& success)
28: CECalendar(aLocale, success)
29{
30}
31
32CopticCalendar::CopticCalendar (const CopticCalendar& other)
33: CECalendar(other)
34{
35}
36
37CopticCalendar::~CopticCalendar()
38{
39}
40
41Calendar*
42CopticCalendar::clone() const
43{
44    return new CopticCalendar(*this);
45}
46
47const char*
48CopticCalendar::getType() const
49{
50    return "coptic";
51}
52
53//-------------------------------------------------------------------------
54// Calendar framework
55//-------------------------------------------------------------------------
56
57int32_t
58CopticCalendar::handleGetExtendedYear()
59{
60    int32_t eyear;
61    if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
62        eyear = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1
63    } else {
64        // The year defaults to the epoch start, the era to CE
65        int32_t era = internalGet(UCAL_ERA, CE);
66        if (era == BCE) {
67            eyear = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year
68        } else {
69            eyear = internalGet(UCAL_YEAR, 1); // Default to year 1
70        }
71    }
72    return eyear;
73}
74
75void
76CopticCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/)
77{
78    int32_t eyear, month, day, era, year;
79    jdToCE(julianDay, getJDEpochOffset(), eyear, month, day);
80
81    if (eyear <= 0) {
82        era = BCE;
83        year = 1 - eyear;
84    } else {
85        era = CE;
86        year = eyear;
87    }
88
89    internalSet(UCAL_EXTENDED_YEAR, eyear);
90    internalSet(UCAL_ERA, era);
91    internalSet(UCAL_YEAR, year);
92    internalSet(UCAL_MONTH, month);
93    internalSet(UCAL_DATE, day);
94    internalSet(UCAL_DAY_OF_YEAR, (30 * month) + day);
95}
96
97const UDate     CopticCalendar::fgSystemDefaultCentury        = DBL_MIN;
98const int32_t   CopticCalendar::fgSystemDefaultCenturyYear    = -1;
99
100UDate           CopticCalendar::fgSystemDefaultCenturyStart       = DBL_MIN;
101int32_t         CopticCalendar::fgSystemDefaultCenturyStartYear   = -1;
102
103UDate
104CopticCalendar::defaultCenturyStart() const
105{
106    initializeSystemDefaultCentury();
107
108    // use defaultCenturyStart unless it's the flag value;
109    // then use systemDefaultCenturyStart
110    return fgSystemDefaultCenturyStart;
111}
112
113int32_t
114CopticCalendar::defaultCenturyStartYear() const
115{
116    initializeSystemDefaultCentury();
117
118    // use defaultCenturyStart unless it's the flag value;
119    // then use systemDefaultCenturyStart
120    return fgSystemDefaultCenturyStartYear;
121}
122
123void
124CopticCalendar::initializeSystemDefaultCentury()
125{
126    // lazy-evaluate systemDefaultCenturyStart
127    UBool needsUpdate;
128    UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
129
130    if (!needsUpdate) {
131        return;
132    }
133
134    UErrorCode status = U_ZERO_ERROR;
135
136    CopticCalendar calendar(Locale("@calendar=coptic"), status);
137    if (U_SUCCESS(status)) {
138        calendar.setTime(Calendar::getNow(), status);
139        calendar.add(UCAL_YEAR, -80, status);
140        UDate    newStart = calendar.getTime(status);
141        int32_t  newYear  = calendar.get(UCAL_YEAR, status);
142        {
143            umtx_lock(NULL);
144            fgSystemDefaultCenturyStartYear = newYear;
145            fgSystemDefaultCenturyStart = newStart;
146            umtx_unlock(NULL);
147        }
148    }
149    // We have no recourse upon failure unless we want to propagate the failure
150    // out.
151}
152
153int32_t
154CopticCalendar::getJDEpochOffset() const
155{
156    return COPTIC_JD_EPOCH_OFFSET;
157}
158
159
160#if 0
161// We do not want to introduce this API in ICU4C.
162// It was accidentally introduced in ICU4J as a public API.
163
164//-------------------------------------------------------------------------
165// Calendar system Conversion methods...
166//-------------------------------------------------------------------------
167
168int32_t
169CopticCalendar::copticToJD(int32_t year, int32_t month, int32_t day)
170{
171    return CECalendar::ceToJD(year, month, day, COPTIC_JD_EPOCH_OFFSET);
172}
173#endif
174
175U_NAMESPACE_END
176
177#endif /* #if !UCONFIG_NO_FORMATTING */
178//eof
179