1/*
2*******************************************************************************
3* Copyright (C) 2003 - 2013, 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
97/**
98 * The system maintains a static default century start date and Year.  They are
99 * initialized the first time they are used.  Once the system default century date
100 * and year are set, they do not change.
101 */
102static UDate           gSystemDefaultCenturyStart       = DBL_MIN;
103static int32_t         gSystemDefaultCenturyStartYear   = -1;
104static icu::UInitOnce  gSystemDefaultCenturyInit        = U_INITONCE_INITIALIZER;
105
106
107static void U_CALLCONV initializeSystemDefaultCentury() {
108    UErrorCode status = U_ZERO_ERROR;
109    CopticCalendar calendar(Locale("@calendar=coptic"), status);
110    if (U_SUCCESS(status)) {
111        calendar.setTime(Calendar::getNow(), status);
112        calendar.add(UCAL_YEAR, -80, status);
113        gSystemDefaultCenturyStart = calendar.getTime(status);
114        gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
115    }
116    // We have no recourse upon failure unless we want to propagate the failure
117    // out.
118}
119
120UDate
121CopticCalendar::defaultCenturyStart() const
122{
123    // lazy-evaluate systemDefaultCenturyStart
124    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
125    return gSystemDefaultCenturyStart;
126}
127
128int32_t
129CopticCalendar::defaultCenturyStartYear() const
130{
131    // lazy-evaluate systemDefaultCenturyStart
132    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
133    return gSystemDefaultCenturyStartYear;
134}
135
136
137int32_t
138CopticCalendar::getJDEpochOffset() const
139{
140    return COPTIC_JD_EPOCH_OFFSET;
141}
142
143
144#if 0
145// We do not want to introduce this API in ICU4C.
146// It was accidentally introduced in ICU4J as a public API.
147
148//-------------------------------------------------------------------------
149// Calendar system Conversion methods...
150//-------------------------------------------------------------------------
151
152int32_t
153CopticCalendar::copticToJD(int32_t year, int32_t month, int32_t day)
154{
155    return CECalendar::ceToJD(year, month, day, COPTIC_JD_EPOCH_OFFSET);
156}
157#endif
158
159U_NAMESPACE_END
160
161#endif /* #if !UCONFIG_NO_FORMATTING */
162//eof
163