1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 1997-2015, International Business Machines Corporation and * 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved. * 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File CALENDAR.CPP 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 959d709d503bab6e2b61931737e662dd293b40578ccornelius* Modification History: 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Date Name Description 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 02/03/97 clhuang Creation. 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 04/22/97 aliu Cleaned up, fixed memory leak, made 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* setWeekCountData() more robust. 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Moved platform code to TPlatformUtilities. 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 05/01/97 aliu Made equals(), before(), after() arguments const. 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 05/20/97 aliu Changed logic of when to compute fields and time 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* to fix bugs. 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 08/12/97 aliu Added equivalentTo. Misc other fixes. 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 07/28/98 stephen Sync up with JDK 1.2 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 09/02/98 stephen Sync with JDK 1.2 8/31 build (getActualMin/Max) 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 03/17/99 stephen Changed adoptTimeZone() - now fAreFieldsSet is 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* set to FALSE to force update of time. 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h" // for 'typeid' to work 2827f654740f2a26ad62a5c155af9199af9e69b889claireho 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h" 34103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/basictz.h" 35103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/simpletz.h" 36103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/rbtz.h" 37103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/vtzone.h" 38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" 39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "buddhcal.h" 40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "taiwncal.h" 41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "japancal.h" 42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "islamcal.h" 43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "hebrwcal.h" 44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "persncal.h" 45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "indiancal.h" 46c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "chnsecal.h" 47c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "coptccal.h" 488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "dangical.h" 49c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "ethpccal.h" 50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h" 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cpputils.h" 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "servloc.h" 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h" 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "locbased.h" 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h" 57b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "ustrenum.h" 58103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uassert.h" 59103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "olsontz.h" 601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#include "sharedcalendar.h" 611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#include "unifiedcache.h" 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic icu::ICULocaleService* gService = NULL; 6559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// INTERNAL - for cleanup 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool calendar_cleanup(void) { 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (gService) { 74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete gService; 75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gService = NULL; 76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 7759d709d503bab6e2b61931737e662dd293b40578ccornelius gServiceInitOnce.reset(); 78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------------ 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Registration 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------- 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//#define U_DEBUG_CALSVC 1 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL) 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 93c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/** 94c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * fldName was removed as a duplicate implementation. 95c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * use udbg_ services instead, 96103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * which depend on include files and library from ../tools/toolutil, the following circular link: 97103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * CPPFLAGS+=-I$(top_srcdir)/tools/toolutil 98103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * LIBS+=$(LIBICUTOOLUTIL) 99c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */ 100103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "udbgutil.h" 101c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include <stdio.h> 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* convert a UCalendarDateFields into a string - for debugging 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param f field enum 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @return static string to the field name 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @internal 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 110c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruconst char* fldName(UCalendarDateFields f) { 111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return udbg_enumName(UDBG_UCalendarDateFields, (int32_t)f); 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if UCAL_DEBUG_DUMP 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// from CalendarTest::calToStr - but doesn't modify contents. 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid ucal_dump(const Calendar &cal) { 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cal.dump(); 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::dump() const { 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int i; 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "@calendar=%s, timeset=%c, fieldset=%c, allfields=%c, virtualset=%c, t=%.2f", 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getType(), fIsTimeSet?'y':'n', fAreFieldsSet?'y':'n', fAreAllFieldsSet?'y':'n', 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsVirtuallySet?'y':'n', 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fTime); 126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // can add more things here: DST, zone, etc. 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "\n"); 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for(i = 0;i<UCAL_FIELD_COUNT;i++) { 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int n; 131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const char *f = fldName((UCalendarDateFields)i); 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, " %25s: %-11ld", f, fFields[i]); 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(fStamp[i] == kUnset) { 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, " (unset) "); 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(fStamp[i] == kInternallySet) { 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, " (internally set) "); 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //} else if(fStamp[i] == kInternalDefault) { 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fprintf(stderr, " (internal default) "); 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, " %%%d ", fStamp[i]); 141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "\n"); 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC void ucal_dump(UCalendar* cal) { 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ucal_dump( *((Calendar*)cal) ); 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* Max value for stamp allowable before recalculation */ 155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define STAMP_MAX 10000 156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char * const gCalTypes[] = { 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru "gregorian", 159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "japanese", 160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "buddhist", 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "roc", 162b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "persian", 163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "islamic-civil", 164b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "islamic", 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "hebrew", 166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "chinese", 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "indian", 168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "coptic", 169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "ethiopic", 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru "ethiopic-amete-alem", 171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho "iso8601", 1728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius "dangi", 17359d709d503bab6e2b61931737e662dd293b40578ccornelius "islamic-umalqura", 17459d709d503bab6e2b61931737e662dd293b40578ccornelius "islamic-tbla", 17559d709d503bab6e2b61931737e662dd293b40578ccornelius "islamic-rgsa", 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru NULL 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// Must be in the order of gCalTypes above 180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querutypedef enum ECalType { 181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_UNKNOWN = -1, 182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_GREGORIAN = 0, 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_JAPANESE, 184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_BUDDHIST, 185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_ROC, 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_PERSIAN, 187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_ISLAMIC_CIVIL, 188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_ISLAMIC, 189b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_HEBREW, 190b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_CHINESE, 191b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_INDIAN, 192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_COPTIC, 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru CALTYPE_ETHIOPIC, 194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho CALTYPE_ETHIOPIC_AMETE_ALEM, 1958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius CALTYPE_ISO8601, 19659d709d503bab6e2b61931737e662dd293b40578ccornelius CALTYPE_DANGI, 19759d709d503bab6e2b61931737e662dd293b40578ccornelius CALTYPE_ISLAMIC_UMALQURA, 19859d709d503bab6e2b61931737e662dd293b40578ccornelius CALTYPE_ISLAMIC_TBLA, 19959d709d503bab6e2b61931737e662dd293b40578ccornelius CALTYPE_ISLAMIC_RGSA 200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} ECalType; 201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2041b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertSharedCalendar::~SharedCalendar() { 2051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert delete ptr; 2061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 2071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 2081b7d32f919554dda9c193b32188251337bc756f1Fredrik Rouberttemplate<> U_I18N_API 2091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertconst SharedCalendar *LocaleCacheKey<SharedCalendar>::createObject( 2101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const void * /*unusedCreationContext*/, UErrorCode &status) const { 2111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert Calendar *calendar = Calendar::makeInstance(fLoc, status); 2121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (U_FAILURE(status)) { 2131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return NULL; 2141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert SharedCalendar *shared = new SharedCalendar(calendar); 2161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (shared == NULL) { 2171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert delete calendar; 2181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert status = U_MEMORY_ALLOCATION_ERROR; 2191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return NULL; 2201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert shared->addRef(); 2221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return shared; 2231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 2241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ECalType getCalendarType(const char *s) { 226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for (int i = 0; gCalTypes[i] != NULL; i++) { 227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (uprv_stricmp(s, gCalTypes[i]) == 0) { 228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return (ECalType)i; 229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return CALTYPE_UNKNOWN; 232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status) { 235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return FALSE; 237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ECalType calType = getCalendarType(keyword); 239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return (calType != CALTYPE_UNKNOWN); 240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void getCalendarKeyword(const UnicodeString &id, char *targetBuffer, int32_t targetBufferSize) { 243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString calendarKeyword = UNICODE_STRING_SIMPLE("calendar="); 244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t calKeyLen = calendarKeyword.length(); 245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t keyLen = 0; 246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t keywordIdx = id.indexOf((UChar)0x003D); /* '=' */ 248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (id[0] == 0x40/*'@'*/ 249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && id.compareBetween(1, keywordIdx+1, calendarKeyword, 0, calKeyLen) == 0) 250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru keyLen = id.extract(keywordIdx+1, id.length(), targetBuffer, targetBufferSize, US_INV); 252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru targetBuffer[keyLen] = 0; 254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 256b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic ECalType getCalendarTypeForLocale(const char *locid) { 257b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 258b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ECalType calType = CALTYPE_UNKNOWN; 259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 260b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru //TODO: ULOC_FULL_NAME is out of date and too small.. 261b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char canonicalName[256]; 262b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // canonicalize, so grandfathered variant will be transformed to keywords 264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // e.g ja_JP_TRADITIONAL -> ja_JP@calendar=japanese 265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t canonicalLen = uloc_canonicalize(locid, canonicalName, sizeof(canonicalName) - 1, &status); 266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return CALTYPE_GREGORIAN; 268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru canonicalName[canonicalLen] = 0; // terminate 270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char calTypeBuf[32]; 272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t calTypeBufLen; 273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calTypeBufLen = uloc_getKeywordValue(canonicalName, "calendar", calTypeBuf, sizeof(calTypeBuf) - 1, &status); 275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(status)) { 276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calTypeBuf[calTypeBufLen] = 0; 277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calType = getCalendarType(calTypeBuf); 278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (calType != CALTYPE_UNKNOWN) { 279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return calType; 280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_ZERO_ERROR; 283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // when calendar keyword is not available or not supported, read supplementalData 285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // to get the default calendar type for the locale's region 286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char region[ULOC_COUNTRY_CAPACITY]; 287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t regionLen = 0; 288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru regionLen = uloc_getCountry(canonicalName, region, sizeof(region) - 1, &status); 289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (regionLen == 0) { 290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char fullLoc[256]; 291103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uloc_addLikelySubtags(locid, fullLoc, sizeof(fullLoc) - 1, &status); 292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru regionLen = uloc_getCountry(fullLoc, region, sizeof(region) - 1, &status); 293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 294b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return CALTYPE_GREGORIAN; 296b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru region[regionLen] = 0; 298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // Read preferred calendar values from supplementalData calendarPreference 300b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status); 301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_getByKey(rb, "calendarPreferenceData", rb, &status); 302b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *order = ures_getByKey(rb, region, NULL, &status); 303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (status == U_MISSING_RESOURCE_ERROR && rb != NULL) { 304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_ZERO_ERROR; 305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru order = ures_getByKey(rb, "001", NULL, &status); 306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calTypeBuf[0] = 0; 309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(status) && order != NULL) { 310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // the first calender type is the default for the region 311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t len = 0; 312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar *uCalType = ures_getStringByIndex(order, 0, &len, &status); 313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (len < (int32_t)sizeof(calTypeBuf)) { 314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u_UCharsToChars(uCalType, calTypeBuf, len); 315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *(calTypeBuf + len) = 0; // terminate; 316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calType = getCalendarType(calTypeBuf); 317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(order); 321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(rb); 322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (calType == CALTYPE_UNKNOWN) { 324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // final fallback 325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru calType = CALTYPE_GREGORIAN; 326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return calType; 328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UErrorCode& status) { 331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru Calendar *cal = NULL; 332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru switch (calType) { 334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_GREGORIAN: 335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new GregorianCalendar(loc, status); 336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_JAPANESE: 338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new JapaneseCalendar(loc, status); 339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_BUDDHIST: 341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new BuddhistCalendar(loc, status); 342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_ROC: 344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new TaiwanCalendar(loc, status); 345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_PERSIAN: 347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new PersianCalendar(loc, status); 348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 34959d709d503bab6e2b61931737e662dd293b40578ccornelius case CALTYPE_ISLAMIC_TBLA: 35059d709d503bab6e2b61931737e662dd293b40578ccornelius cal = new IslamicCalendar(loc, status, IslamicCalendar::TBLA); 35159d709d503bab6e2b61931737e662dd293b40578ccornelius break; 352b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_ISLAMIC_CIVIL: 353b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new IslamicCalendar(loc, status, IslamicCalendar::CIVIL); 354b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 35559d709d503bab6e2b61931737e662dd293b40578ccornelius case CALTYPE_ISLAMIC_RGSA: 35659d709d503bab6e2b61931737e662dd293b40578ccornelius // default any region specific not handled individually to islamic 357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_ISLAMIC: 358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new IslamicCalendar(loc, status, IslamicCalendar::ASTRONOMICAL); 359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 36059d709d503bab6e2b61931737e662dd293b40578ccornelius case CALTYPE_ISLAMIC_UMALQURA: 36159d709d503bab6e2b61931737e662dd293b40578ccornelius cal = new IslamicCalendar(loc, status, IslamicCalendar::UMALQURA); 36259d709d503bab6e2b61931737e662dd293b40578ccornelius break; 363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_HEBREW: 364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new HebrewCalendar(loc, status); 365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_CHINESE: 367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new ChineseCalendar(loc, status); 368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_INDIAN: 370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new IndianCalendar(loc, status); 371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_COPTIC: 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new CopticCalendar(loc, status); 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_ETHIOPIC: 376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new EthiopicCalendar(loc, status, EthiopicCalendar::AMETE_MIHRET_ERA); 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru case CALTYPE_ETHIOPIC_AMETE_ALEM: 379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru cal = new EthiopicCalendar(loc, status, EthiopicCalendar::AMETE_ALEM_ERA); 380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru break; 381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case CALTYPE_ISO8601: 382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cal = new GregorianCalendar(loc, status); 383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cal->setFirstDayOfWeek(UCAL_MONDAY); 384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cal->setMinimalDaysInFirstWeek(4); 385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 3868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius case CALTYPE_DANGI: 3878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius cal = new DangiCalendar(loc, status); 3888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius break; 389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru default: 390b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_UNSUPPORTED_ERROR; 391b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 392b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return cal; 393b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 394b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 395b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* a Calendar Factory which creates the "basic" calendar types, that is, those 402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* shipped with ICU. 403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass BasicCalendarFactory : public LocaleKeyFactory { 405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic: 406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /** 407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param calendarType static const string (caller owns storage - will be aliased) to calendar type 408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru BasicCalendarFactory() 410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru : LocaleKeyFactory(LocaleKeyFactory::INVISIBLE) { } 411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 412103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~BasicCalendarFactory(); 413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprotected: 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //virtual UBool isSupportedID( const UnicodeString& id, UErrorCode& status) const { 416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if(U_FAILURE(status)) { 417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return FALSE; 418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // } 419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // char keyword[ULOC_FULLNAME_CAPACITY]; 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // getCalendarKeyword(id, keyword, (int32_t)sizeof(keyword)); 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // return isStandardSupportedKeyword(keyword, status); 422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //} 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual void updateVisibleIDs(Hashtable& result, UErrorCode& status) const 425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) { 427b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru for(int32_t i=0;gCalTypes[i] != NULL;i++) { 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString id((UChar)0x40); /* '@' a variant character */ 429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru id.append(UNICODE_STRING_SIMPLE("calendar=")); 430b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru id.append(UnicodeString(gCalTypes[i], -1, US_INV)); 431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result.put(id, (void*)this, status); 432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual UObject* create(const ICUServiceKey& key, const ICUService* /*service*/, UErrorCode& status) const { 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 43827f654740f2a26ad62a5c155af9199af9e69b889claireho if(dynamic_cast<const LocaleKey*>(&key) == NULL) { 439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "::create - not a LocaleKey!\n"); 440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru const LocaleKey& lkey = (LocaleKey&)key; 443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale curLoc; // current locale 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale canLoc; // Canonical locale 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lkey.currentLocale(curLoc); 447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lkey.canonicalLocale(canLoc); 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char keyword[ULOC_FULLNAME_CAPACITY]; 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UnicodeString str; 451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru key.currentID(str); 453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getCalendarKeyword(str, keyword, (int32_t) sizeof(keyword)); 454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "BasicCalendarFactory::create() - cur %s, can %s\n", (const char*)curLoc.getName(), (const char*)canLoc.getName()); 457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!isStandardSupportedKeyword(keyword,status)) { // Do we handle this type? 460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "BasicCalendarFactory - not handling %s.[%s]\n", (const char*) curLoc.getName(), tmp ); 463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 467b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return createStandardCalendar(getCalendarType(keyword), canLoc, status); 468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 471103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusBasicCalendarFactory::~BasicCalendarFactory() {} 472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* A factory which looks up the DefaultCalendar resource to determine which class of calendar to use 475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass DefaultCalendarFactory : public ICUResourceBundleFactory { 478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic: 479103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius DefaultCalendarFactory() : ICUResourceBundleFactory() { } 480103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~DefaultCalendarFactory(); 481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprotected: 482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual UObject* create(const ICUServiceKey& key, const ICUService* /*service*/, UErrorCode& status) const { 483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LocaleKey &lkey = (LocaleKey&)key; 485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale loc; 486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lkey.currentLocale(loc); 487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 488b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString *ret = new UnicodeString(); 489b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (ret == NULL) { 490b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 492b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ret->append((UChar)0x40); // '@' is a variant character 493b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ret->append(UNICODE_STRING("calendar=", 9)); 494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ret->append(UnicodeString(gCalTypes[getCalendarTypeForLocale(loc.getName())], -1, US_INV)); 495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 496b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return ret; 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 500103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusDefaultCalendarFactory::~DefaultCalendarFactory() {} 501103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass CalendarService : public ICULocaleService { 504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic: 505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru CalendarService() 506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru : ICULocaleService(UNICODE_STRING_SIMPLE("Calendar")) 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru registerFactory(new DefaultCalendarFactory(), status); 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 512103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~CalendarService(); 513103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual UObject* cloneInstance(UObject* instance) const { 51527f654740f2a26ad62a5c155af9199af9e69b889claireho UnicodeString *s = dynamic_cast<UnicodeString *>(instance); 51627f654740f2a26ad62a5c155af9199af9e69b889claireho if(s != NULL) { 51727f654740f2a26ad62a5c155af9199af9e69b889claireho return s->clone(); 518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC_F 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status2 = U_ZERO_ERROR; 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Cloning a %s calendar with tz=%ld\n", ((Calendar*)instance)->getType(), ((Calendar*)instance)->get(UCAL_ZONE_OFFSET, status2)); 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return ((Calendar*)instance)->clone(); 524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /*actualID*/, UErrorCode& status) const { 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru LocaleKey& lkey = (LocaleKey&)key; 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //int32_t kind = lkey.kind(); 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale loc; 532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lkey.canonicalLocale(loc); 533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale loc2; 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lkey.currentLocale(loc2); 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "CalSvc:handleDefault for currentLoc %s, canloc %s\n", (const char*)loc.getName(), (const char*)loc2.getName()); 538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar *nc = new GregorianCalendar(loc, status); 540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status2 = U_ZERO_ERROR; 543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "New default calendar has tz=%d\n", ((Calendar*)nc)->get(UCAL_ZONE_OFFSET, status2)); 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return nc; 546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru virtual UBool isDefault() const { 549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return countFactories() == 1; 550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 553103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendarService::~CalendarService() {} 554103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic inline UBool 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruisCalendarServiceUsed() { 55959d709d503bab6e2b61931737e662dd293b40578ccornelius return !gServiceInitOnce.isReset(); 560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 56459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV 56559d709d503bab6e2b61931737e662dd293b40578ccorneliusinitCalendarService(UErrorCode &status) 566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Spinning up Calendar Service\n"); 569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 57059d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_CALENDAR, calendar_cleanup); 57159d709d503bab6e2b61931737e662dd293b40578ccornelius gService = new CalendarService(); 57259d709d503bab6e2b61931737e662dd293b40578ccornelius if (gService == NULL) { 573c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 57459d709d503bab6e2b61931737e662dd293b40578ccornelius return; 575c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Registering classes..\n"); 578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Register all basic instances. 58159d709d503bab6e2b61931737e662dd293b40578ccornelius gService->registerFactory(new BasicCalendarFactory(),status); 582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Done..\n"); 585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "err (%s) registering classes, deleting service.....\n", u_errorName(status)); 590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 59159d709d503bab6e2b61931737e662dd293b40578ccornelius delete gService; 59259d709d503bab6e2b61931737e662dd293b40578ccornelius gService = NULL; 59359d709d503bab6e2b61931737e662dd293b40578ccornelius } 594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 59659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic ICULocaleService* 59759d709d503bab6e2b61931737e662dd293b40578ccorneliusgetCalendarService(UErrorCode &status) 59859d709d503bab6e2b61931737e662dd293b40578ccornelius{ 59959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gServiceInitOnce, &initCalendarService, status); 600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return gService; 601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruURegistryKey Calendar::registerFactory(ICUServiceFactory* toAdopt, UErrorCode& status) 604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getCalendarService(status)->registerFactory(toAdopt, status); 606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool Calendar::unregister(URegistryKey key, UErrorCode& status) { 609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getCalendarService(status)->unregister(key, status); 610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* UCONFIG_NO_SERVICE */ 612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t kCalendarLimits[UCAL_FIELD_COUNT][4] = { 616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Minimum Greatest min Least max Greatest max 617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // ERA 618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // YEAR 619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // MONTH 620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // WEEK_OF_YEAR 621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // WEEK_OF_MONTH 622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // DAY_OF_MONTH 623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // DAY_OF_YEAR 624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1, 1, 7, 7 }, // DAY_OF_WEEK 625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // DAY_OF_WEEK_IN_MONTH 626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 1, 1 }, // AM_PM 627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 11, 11 }, // HOUR 628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 23, 23 }, // HOUR_OF_DAY 629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 59, 59 }, // MINUTE 630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 59, 59 }, // SECOND 631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 999, 999 }, // MILLISECOND 632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {-12*kOneHour, -12*kOneHour, 12*kOneHour, 15*kOneHour }, // ZONE_OFFSET 633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 0, 0, 1*kOneHour, 1*kOneHour }, // DST_OFFSET 634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // YEAR_WOY 635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1, 1, 7, 7 }, // DOW_LOCAL 636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {/*N/A*/-1, /*N/A*/-1, /*N/A*/-1, /*N/A*/-1}, // EXTENDED_YEAR 637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { -0x7F000000, -0x7F000000, 0x7F000000, 0x7F000000 }, // JULIAN_DAY 6381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert { 0, 0, 24*kOneHour-1, 24*kOneHour-1 }, // MILLISECONDS_IN_DAY 6391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert { 0, 0, 1, 1 }, // IS_LEAP_MONTH 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Resource bundle tags read by this class 643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gMonthNames[] = "monthNames"; 644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Data flow in Calendar 646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// --------------------- 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// The current time is represented in two ways by Calendar: as UTC 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// milliseconds from the epoch start (1 January 1970 0:00 UTC), and as local 650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// fields such as MONTH, HOUR, AM_PM, etc. It is possible to compute the 651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// millis from the fields, and vice versa. The data needed to do this 652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// conversion is encapsulated by a TimeZone object owned by the Calendar. 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// The data provided by the TimeZone object may also be overridden if the 654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// user sets the ZONE_OFFSET and/or DST_OFFSET fields directly. The class 655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// keeps track of what information was most recently set by the caller, and 656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// uses that to compute any other information as needed. 657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// If the user sets the fields using set(), the data flow is as follows. 659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// This is implemented by the Calendar subclass's computeTime() method. 660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// During this process, certain fields may be ignored. The disambiguation 661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// algorithm for resolving which fields to pay attention to is described 662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// above. 663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) 665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | 666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | Using Calendar-specific algorithm 667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// V 668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// local standard millis 669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | 670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | Using TimeZone or user-set ZONE_OFFSET / DST_OFFSET 671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// V 672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UTC millis (in time data member) 673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// If the user sets the UTC millis using setTime(), the data flow is as 675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// follows. This is implemented by the Calendar subclass's computeFields() 676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// method. 677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// UTC millis (in time data member) 679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | 680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | Using TimeZone getOffset() 681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// V 682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// local standard millis 683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | 684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// | Using Calendar-specific algorithm 685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// V 686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// local fields (YEAR, MONTH, DATE, HOUR, MINUTE, etc.) 687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// In general, a round trip from fields, through local and UTC millis, and 689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// back out to fields is made when necessary. This is implemented by the 690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// complete() method. Resolving a partial set of fields into a UTC millis 691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// value allows all remaining fields to be generated from that value. If 692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// the Calendar is lenient, the fields are also renormalized to standard 693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ranges when they are regenerated. 694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::Calendar(UErrorCode& success) 698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: UObject(), 699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsTimeSet(FALSE), 700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsSet(FALSE), 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreAllFieldsSet(FALSE), 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsVirtuallySet(FALSE), 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufNextStamp((int32_t)kMinimumUserStamp), 704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufTime(0), 705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufLenient(TRUE), 706f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusfZone(NULL), 707103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfRepeatedWallTime(UCAL_WALLTIME_LAST), 708103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfSkippedWallTime(UCAL_WALLTIME_LAST) 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clear(); 711f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (U_FAILURE(success)) { 712f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return; 713f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fZone = TimeZone::createDefault(); 715c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (fZone == NULL) { 716c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru success = U_MEMORY_ALLOCATION_ERROR; 717c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 71850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho setWeekData(Locale::getDefault(), NULL, success); 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::Calendar(TimeZone* zone, const Locale& aLocale, UErrorCode& success) 724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: UObject(), 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsTimeSet(FALSE), 726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsSet(FALSE), 727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreAllFieldsSet(FALSE), 728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsVirtuallySet(FALSE), 729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufNextStamp((int32_t)kMinimumUserStamp), 730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufTime(0), 731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufLenient(TRUE), 732f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusfZone(NULL), 733103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfRepeatedWallTime(UCAL_WALLTIME_LAST), 734103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfSkippedWallTime(UCAL_WALLTIME_LAST) 735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 736f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (U_FAILURE(success)) { 737f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return; 738f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(zone == 0) { 740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because timezone cannot be 0\n", 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__); 743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru success = U_ILLEGAL_ARGUMENT_ERROR; 745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clear(); 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fZone = zone; 75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho setWeekData(aLocale, NULL, success); 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::Calendar(const TimeZone& zone, const Locale& aLocale, UErrorCode& success) 756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: UObject(), 757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufIsTimeSet(FALSE), 758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsSet(FALSE), 759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreAllFieldsSet(FALSE), 760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufAreFieldsVirtuallySet(FALSE), 761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufNextStamp((int32_t)kMinimumUserStamp), 762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufTime(0), 763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerufLenient(TRUE), 764f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusfZone(NULL), 765103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfRepeatedWallTime(UCAL_WALLTIME_LAST), 766103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusfSkippedWallTime(UCAL_WALLTIME_LAST) 767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 768f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (U_FAILURE(success)) { 769f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return; 770f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clear(); 772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fZone = zone.clone(); 773c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (fZone == NULL) { 774fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius success = U_MEMORY_ALLOCATION_ERROR; 775c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 77650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho setWeekData(aLocale, NULL, success); 777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::~Calendar() 782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete fZone; 784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::Calendar(const Calendar &source) 789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru: UObject(source) 790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 791f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius fZone = NULL; 792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *this = source; 793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar & 798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::operator=(const Calendar &right) 799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (this != &right) { 801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_arrayCopy(right.fFields, fFields, UCAL_FIELD_COUNT); 802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_arrayCopy(right.fIsSet, fIsSet, UCAL_FIELD_COUNT); 803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_arrayCopy(right.fStamp, fStamp, UCAL_FIELD_COUNT); 804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fTime = right.fTime; 805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = right.fIsTimeSet; 806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreAllFieldsSet = right.fAreAllFieldsSet; 807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = right.fAreFieldsSet; 808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsVirtuallySet = right.fAreFieldsVirtuallySet; 809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fLenient = right.fLenient; 810103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fRepeatedWallTime = right.fRepeatedWallTime; 811103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fSkippedWallTime = right.fSkippedWallTime; 812f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius delete fZone; 813f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius fZone = NULL; 814c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (right.fZone != NULL) { 815c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru fZone = right.fZone->clone(); 816c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFirstDayOfWeek = right.fFirstDayOfWeek; 818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fMinimalDaysInFirstWeek = right.fMinimalDaysInFirstWeek; 81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnset = right.fWeekendOnset; 82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnsetMillis = right.fWeekendOnsetMillis; 82150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCease = right.fWeekendCease; 82250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCeaseMillis = right.fWeekendCeaseMillis; 823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fNextStamp = right.fNextStamp; 824103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_strcpy(validLocale, right.validLocale); 825103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_strcpy(actualLocale, right.actualLocale); 826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return *this; 829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar* U_EXPORT2 834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::createInstance(UErrorCode& success) 835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return createInstance(TimeZone::createDefault(), Locale::getDefault(), success); 837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar* U_EXPORT2 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::createInstance(const TimeZone& zone, UErrorCode& success) 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return createInstance(zone, Locale::getDefault(), success); 845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar* U_EXPORT2 850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::createInstance(const Locale& aLocale, UErrorCode& success) 851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return createInstance(TimeZone::createDefault(), aLocale, success); 853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- Adopting 856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Note: this is the bottleneck that actually calls the service routines. 858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 8591b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCalendar * U_EXPORT2 8601b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCalendar::makeInstance(const Locale& aLocale, UErrorCode& success) { 861b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(success)) { 862b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 863b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 864b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale actualLoc; 866b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UObject* u = NULL; 867b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isCalendarServiceUsed()) { 870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u = getCalendarService(success)->get(aLocale, LocaleKey::KIND_ANY, &actualLoc, success); 871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else 873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 875b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru u = createStandardCalendar(getCalendarTypeForLocale(aLocale.getName()), aLocale, success); 876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar* c = NULL; 878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(success) || !u) { 880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_SUCCESS(success)) { // Propagate some kind of err 881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru success = U_INTERNAL_PROGRAM_ERROR; 882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_SERVICE 88727f654740f2a26ad62a5c155af9199af9e69b889claireho const UnicodeString* str = dynamic_cast<const UnicodeString*>(u); 88827f654740f2a26ad62a5c155af9199af9e69b889claireho if(str != NULL) { 889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It's a unicode string telling us what type of calendar to load ("gregorian", etc) 890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Create a Locale over this string 891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale l(""); 89227f654740f2a26ad62a5c155af9199af9e69b889claireho LocaleUtility::initLocaleFromName(*str, l); 893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "Calendar::createInstance(%s), looking up [%s]\n", aLocale.getName(), l.getName()); 896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Locale actualLoc2; 899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete u; 900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u = NULL; 901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Don't overwrite actualLoc, since the actual loc from this call 903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // may be something like "@calendar=gregorian" -- TODO investigate 904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // further... 905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY, &actualLoc2, success); 906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(success) || !c) { 908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_SUCCESS(success)) { 909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err 910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91427f654740f2a26ad62a5c155af9199af9e69b889claireho str = dynamic_cast<const UnicodeString*>(c); 91527f654740f2a26ad62a5c155af9199af9e69b889claireho if(str != NULL) { 916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // recursed! Second lookup returned a UnicodeString. 917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Perhaps DefaultCalendar{} was set to another locale. 918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char tmp[200]; 920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Extract a char* out of it.. 92127f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t len = str->length(); 922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t actLen = sizeof(tmp)-1; 923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(len > actLen) { 924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = actLen; 925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 92627f654740f2a26ad62a5c155af9199af9e69b889claireho str->extract(0,len,tmp); 927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru tmp[len]=0; 928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "err - recursed, 2nd lookup was unistring %s\n", tmp); 930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru success = U_MISSING_RESOURCE_ERROR; // requested a calendar type which could NOT be found. 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete c; 933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_CALSVC 936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%p: setting week count data to locale %s, actual locale %s\n", c, (const char*)aLocale.getName(), (const char *)actualLoc.getName()); 937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 93850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho c->setWeekData(aLocale, c->getType(), success); // set the correct locale (this was an indirected calendar) 939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char keyword[ULOC_FULLNAME_CAPACITY]; 941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpStatus = U_ZERO_ERROR; 942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho l.getKeywordValue("calendar", keyword, ULOC_FULLNAME_CAPACITY, tmpStatus); 943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus) && uprv_strcmp(keyword, "iso8601") == 0) { 944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho c->setFirstDayOfWeek(UCAL_MONDAY); 945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho c->setMinimalDaysInFirstWeek(4); 946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else 949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* UCONFIG_NO_SERVICE */ 950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a calendar was returned - we assume the factory did the right thing. 952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c = (Calendar*)u; 953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return c; 9561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 9571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 9581b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCalendar* U_EXPORT2 9591b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCalendar::createInstance(TimeZone* zone, const Locale& aLocale, UErrorCode& success) 9601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert{ 9611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert LocalPointer<TimeZone> zonePtr(zone); 9621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const SharedCalendar *shared = NULL; 9631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnifiedCache::getByLocale(aLocale, shared, success); 9641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (U_FAILURE(success)) { 9651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return NULL; 9661b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 9671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert Calendar *c = (*shared)->clone(); 9681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert shared->removeRef(); 9691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (c == NULL) { 9701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert success = U_MEMORY_ALLOCATION_ERROR; 9711b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return NULL; 9721b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 9731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now, reset calendar to default state: 9751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert c->adoptTimeZone(zonePtr.orphan()); // Set the correct time zone 976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c->setTimeInMillis(getNow(), success); // let the new calendar have the current time. 977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar* U_EXPORT2 984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode& success) 985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar* c = createInstance(aLocale, success); 987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_SUCCESS(success) && c) { 988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru c->setTimeZone(zone); 989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return c; 991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid U_EXPORT2 9961b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCalendar::getCalendarTypeFromLocale( 9971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const Locale &aLocale, 9981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert char *typeBuffer, 9991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t typeBufferSize, 10001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UErrorCode &success) { 10011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const SharedCalendar *shared = NULL; 10021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnifiedCache::getByLocale(aLocale, shared, success); 10031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (U_FAILURE(success)) { 10041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 10051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 10061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uprv_strncpy(typeBuffer, (*shared)->getType(), typeBufferSize); 10071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert shared->removeRef(); 10081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if (typeBuffer[typeBufferSize - 1]) { 10091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert success = U_BUFFER_OVERFLOW_ERROR; 10101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 10111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 10121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::operator==(const Calendar& that) const 1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return isEquivalentTo(that) && 1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTimeInMillis(status) == that.getTimeInMillis(status) && 1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_SUCCESS(status); 1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::isEquivalentTo(const Calendar& other) const 1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 102527f654740f2a26ad62a5c155af9199af9e69b889claireho return typeid(*this) == typeid(other) && 1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fLenient == other.fLenient && 1027103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fRepeatedWallTime == other.fRepeatedWallTime && 1028103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fSkippedWallTime == other.fSkippedWallTime && 1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFirstDayOfWeek == other.fFirstDayOfWeek && 1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fMinimalDaysInFirstWeek == other.fMinimalDaysInFirstWeek && 103150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnset == other.fWeekendOnset && 103250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnsetMillis == other.fWeekendOnsetMillis && 103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCease == other.fWeekendCease && 103450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCeaseMillis == other.fWeekendCeaseMillis && 1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *fZone == *other.fZone; 1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::equals(const Calendar& when, UErrorCode& status) const 1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (this == &when || 1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTime(status) == when.getTime(status)); 1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::before(const Calendar& when, UErrorCode& status) const 1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (this != &when && 1053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTimeInMillis(status) < when.getTimeInMillis(status)); 1054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::after(const Calendar& when, UErrorCode& status) const 1060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (this != &when && 1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTimeInMillis(status) > when.getTimeInMillis(status)); 1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst Locale* U_EXPORT2 1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getAvailableLocales(int32_t& count) 1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return Locale::getAvailableLocales(count); 1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 107650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoStringEnumeration* U_EXPORT2 107750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::getKeywordValuesForLocale(const char* key, 1078b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const Locale& locale, UBool commonlyUsed, UErrorCode& status) 1079b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{ 1080b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // This is a wrapper over ucal_getKeywordValuesForLocale 1081b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UEnumeration *uenum = ucal_getKeywordValuesForLocale(key, locale.getName(), 1082b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru commonlyUsed, &status); 1083b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 1084b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uenum_close(uenum); 1085b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 1086b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 1087b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return new UStringEnumeration(uenum); 1088b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 1089b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1090b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru// ------------------------------------- 1091b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUDate U_EXPORT2 1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getNow() 1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return uprv_getUTCtime(); // return as milliseconds 1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Gets this Calendar's current time as a long. 1102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @return the current time as UTC milliseconds from the epoch. 1103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querudouble 1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getTimeInMillis(UErrorCode& status) const 1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) 1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0.0; 1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ( ! fIsTimeSet) 1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ((Calendar*)this)->updateTime(status); 1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Test for buffer overflows */ 1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0.0; 1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fTime; 1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Sets this Calendar's current time from the given long value. 112454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* A status of U_ILLEGAL_ARGUMENT_ERROR is set when millis is 112554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* outside the range permitted by a Calendar object when not in lenient mode. 112654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* when in lenient mode the out of range values are pinned to their respective min/max. 1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param date the new time in UTC milliseconds from the epoch. 1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::setTimeInMillis( double millis, UErrorCode& status ) { 1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) 1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (millis > MAX_MILLIS) { 113554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if(isLenient()) { 113654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius millis = MAX_MILLIS; 113754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 113854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius status = U_ILLEGAL_ARGUMENT_ERROR; 113954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return; 114054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (millis < MIN_MILLIS) { 114254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if(isLenient()) { 114354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius millis = MIN_MILLIS; 114454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 114554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius status = U_ILLEGAL_ARGUMENT_ERROR; 114654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return; 114754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fTime = millis; 1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = fAreAllFieldsSet = FALSE; 1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = fAreFieldsVirtuallySet = TRUE; 115350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 115450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) { 115550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fFields[i] = 0; 115650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fStamp[i] = kUnset; 115750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fIsSet[i] = FALSE; 115850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 115950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 116050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::get(UCalendarDateFields field, UErrorCode& status) const 1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // field values are only computed when actually requested; for more on when computation 1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of various things happens, see the "data flow in Calendar" description at the top 1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of this file 1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) ((Calendar*)this)->complete(status); // Cast away const 1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return U_SUCCESS(status) ? fFields[field] : 0; 1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::set(UCalendarDateFields field, int32_t value) 1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fAreFieldsVirtuallySet) { 1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode ec = U_ZERO_ERROR; 1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeFields(ec); 1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[field] = value; 1185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* Ensure that the fNextStamp value doesn't go pass max value for int32_t */ 1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fNextStamp == STAMP_MAX) { 1187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho recalculateStamp(); 1188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fStamp[field] = fNextStamp++; 1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsSet[field] = TRUE; // Remove later 1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = fAreFieldsSet = fAreFieldsVirtuallySet = FALSE; 1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::set(int32_t year, int32_t month, int32_t date) 1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_YEAR, year); 1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MONTH, month); 1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DATE, date); 1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t minute) 1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_YEAR, year); 1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MONTH, month); 1211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DATE, date); 1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_HOUR_OF_DAY, hour); 1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MINUTE, minute); 1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::set(int32_t year, int32_t month, int32_t date, int32_t hour, int32_t minute, int32_t second) 1220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_YEAR, year); 1222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MONTH, month); 1223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DATE, date); 1224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_HOUR_OF_DAY, hour); 1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MINUTE, minute); 1226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_SECOND, second); 1227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// For now the full getRelatedYear implementation is here; 1231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// per #10752 move the non-default implementation to subclasses 1232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// (default implementation will do no year adjustment) 1233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t gregoYearFromIslamicStart(int32_t year) { 1235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // ad hoc conversion, improve under #10752 1236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // rough est for now, ok for grego 1846-2138, 1237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // otherwise occasionally wrong (for 3% of years) 1238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int cycle, offset, shift = 0; 1239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (year >= 1397) { 1240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cycle = (year - 1397) / 67; 1241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offset = (year - 1397) % 67; 1242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius shift = 2*cycle + ((offset >= 33)? 1: 0); 1243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 1244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cycle = (year - 1396) / 67 - 1; 1245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offset = -(year - 1396) % 67; 1246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius shift = 2*cycle + ((offset <= 33)? 1: 0); 1247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return year + 579 - shift; 1249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 1250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t Calendar::getRelatedYear(UErrorCode &status) const 1252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{ 1253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 1254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 1255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t year = get(UCAL_EXTENDED_YEAR, status); 1257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 1258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 1259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // modify for calendar type 1261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ECalType type = getCalendarType(getType()); 1262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (type) { 1263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_PERSIAN: 1264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 622; break; 1265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_HEBREW: 1266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 3760; break; 1267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_CHINESE: 1268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 2637; break; 1269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_INDIAN: 1270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 79; break; 1271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_COPTIC: 1272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 284; break; 1273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ETHIOPIC: 1274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 8; break; 1275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ETHIOPIC_AMETE_ALEM: 1276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -=5492; break; 1277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_DANGI: 1278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 2333; break; 1279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_CIVIL: 1280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC: 1281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_UMALQURA: 1282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_TBLA: 1283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_RGSA: 1284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year = gregoYearFromIslamicStart(year); break; 1285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 1286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_GREGORIAN 1287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_JAPANESE 1288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_BUDDHIST 1289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_ROC 1290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_ISO8601 1291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // do nothing, EXTENDED_YEAR same as Gregorian 1292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 1293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return year; 1295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 1296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// ------------------------------------- 1298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// For now the full setRelatedYear implementation is here; 1299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// per #10752 move the non-default implementation to subclasses 1300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// (default implementation will do no year adjustment) 1301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t firstIslamicStartYearFromGrego(int32_t year) { 1303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // ad hoc conversion, improve under #10752 1304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // rough est for now, ok for grego 1846-2138, 1305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // otherwise occasionally wrong (for 3% of years) 1306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int cycle, offset, shift = 0; 1307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (year >= 1977) { 1308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cycle = (year - 1977) / 65; 1309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offset = (year - 1977) % 65; 1310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius shift = 2*cycle + ((offset >= 32)? 1: 0); 1311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 1312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cycle = (year - 1976) / 65 - 1; 1313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offset = -(year - 1976) % 65; 1314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius shift = 2*cycle + ((offset <= 32)? 1: 0); 1315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return year - 579 + shift; 1317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 1318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid Calendar::setRelatedYear(int32_t year) 1319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{ 1320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // modify for calendar type 1321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ECalType type = getCalendarType(getType()); 1322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (type) { 1323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_PERSIAN: 1324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 622; break; 1325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_HEBREW: 1326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 3760; break; 1327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_CHINESE: 1328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 2637; break; 1329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_INDIAN: 1330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 79; break; 1331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_COPTIC: 1332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 284; break; 1333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ETHIOPIC: 1334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year -= 8; break; 1335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ETHIOPIC_AMETE_ALEM: 1336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year +=5492; break; 1337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_DANGI: 1338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year += 2333; break; 1339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_CIVIL: 1340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC: 1341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_UMALQURA: 1342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_TBLA: 1343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case CALTYPE_ISLAMIC_RGSA: 1344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius year = firstIslamicStartYearFromGrego(year); break; 1345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 1346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_GREGORIAN 1347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_JAPANESE 1348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_BUDDHIST 1349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_ROC 1350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // CALTYPE_ISO8601 1351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // do nothing, EXTENDED_YEAR same as Gregorian 1352fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 1353fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // set extended year 1355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius set(UCAL_EXTENDED_YEAR, year); 1356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 1357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// ------------------------------------- 1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::clear() 1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) { 1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[i] = 0; // Must do this; other code depends on it 1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fStamp[i] = kUnset; 1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsSet[i] = FALSE; // Remove later 1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = fAreFieldsSet = fAreAllFieldsSet = fAreFieldsVirtuallySet = FALSE; 1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fTime is not 'cleared' - may be used if no fields are set. 1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::clear(UCalendarDateFields field) 1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fAreFieldsVirtuallySet) { 1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode ec = U_ZERO_ERROR; 1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeFields(ec); 1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[field] = 0; 1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fStamp[field] = kUnset; 1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsSet[field] = FALSE; // Remove later 1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = fAreFieldsSet = fAreAllFieldsSet = fAreFieldsVirtuallySet = FALSE; 1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::isSet(UCalendarDateFields field) const 1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fAreFieldsVirtuallySet || (fStamp[field] != kUnset); 1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::newestStamp(UCalendarDateFields first, UCalendarDateFields last, int32_t bestStampSoFar) const 1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bestStamp = bestStampSoFar; 1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t i=(int32_t)first; i<=(int32_t)last; ++i) { 1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fStamp[i] > bestStamp) { 1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bestStamp = fStamp[i]; 1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return bestStamp; 1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::complete(UErrorCode& status) 1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!fIsTimeSet) { 1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru updateTime(status); 1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Test for buffer overflows */ 1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!fAreFieldsSet) { 1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeFields(status); // fills in unset fields 1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Test for buffer overflows */ 1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = TRUE; 1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreAllFieldsSet = TRUE; 1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------- 1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Protected utility methods for use by subclasses. These are very handy 1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// for implementing add, roll, and computeFields. 1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//------------------------------------------------------------------------- 1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Adjust the specified field so that it is within 1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* the allowable range for the date to which this calendar is set. 1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* For example, in a Gregorian calendar pinning the {@link #DAY_OF_MONTH DAY_OF_MONTH} 1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* field for a calendar set to April 31 would cause it to be set 1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* to April 30. 1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p> 1443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <b>Subclassing:</b> 1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <br> 1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* This utility method is intended for use by subclasses that need to implement 1446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* their own overrides of {@link #roll roll} and {@link #add add}. 1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p> 1448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <b>Note:</b> 1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <code>pinField</code> is implemented in terms of 1450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* {@link #getActualMinimum getActualMinimum} 1451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* and {@link #getActualMaximum getActualMaximum}. If either of those methods uses 1452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* a slow, iterative algorithm for a particular field, it would be 1453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* unwise to attempt to call <code>pinField</code> for that field. If you 1454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* really do need to do so, you should override this method to do 1455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* something more efficient for that field. 1456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p> 1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param field The calendar field whose value should be pinned. 1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @see #getActualMinimum 1460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @see #getActualMaximum 1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @stable ICU 2.0 1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::pinField(UCalendarDateFields field, UErrorCode& status) { 1464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = getActualMaximum(field, status); 1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t min = getActualMinimum(field, status); 1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFields[field] > max) { 1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, max); 1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (fFields[field] < min) { 1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, min); 1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::computeFields(UErrorCode &ec) 1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(ec)) { 1478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute local wall millis 1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double localMillis = internalGetTime(); 1482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t rawOffset, dstOffset; 1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru getTimeZone().getOffset(localMillis, FALSE, rawOffset, dstOffset, ec); 1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru localMillis += (rawOffset + dstOffset); 1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Mark fields as set. Do this before calling handleComputeFields(). 1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint32_t mask = //fInternalSetMask; 1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_ERA) | 1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_YEAR) | 1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_MONTH) | 1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_DAY_OF_MONTH) | // = UCAL_DATE 1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_DAY_OF_YEAR) | 1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (1 << UCAL_EXTENDED_YEAR); 1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) { 1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((mask & 1) == 0) { 1497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fStamp[i] = kInternallySet; 1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsSet[i] = TRUE; // Remove later 1499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fStamp[i] = kUnset; 1501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsSet[i] = FALSE; // Remove later 1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mask >>= 1; 1504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We used to check for and correct extreme millis values (near 1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Long.MIN_VALUE or Long.MAX_VALUE) here. Such values would cause 1508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // overflows from positive to negative (or vice versa) and had to 1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // be manually tweaked. We no longer need to do this because we 1510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // have limited the range of supported dates to those that have a 1511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Julian day that fits into an int. This allows us to implement a 1512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // JULIAN_DAY field and also removes some inelegant code. - Liu 1513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 11/6/00 1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1515b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t days = (int32_t)ClockMath::floorDivide(localMillis, (double)kOneDay); 1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_JULIAN_DAY,days + kEpochStartAsJulianDay); 1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //fprintf(stderr, "%s:%d- Hmm! Jules @ %d, as per %.0lf millis\n", 1521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //__FILE__, __LINE__, fFields[UCAL_JULIAN_DAY], localMillis); 1522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 1523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeGregorianAndDOWFields(fFields[UCAL_JULIAN_DAY], ec); 1525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Call framework method to have subclass compute its fields. 1527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // These must include, at a minimum, MONTH, DAY_OF_MONTH, 1528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // EXTENDED_YEAR, YEAR, DAY_OF_YEAR. This method will call internalSet(), 1529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // which will update stamp[]. 1530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru handleComputeFields(fFields[UCAL_JULIAN_DAY], ec); 1531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute week-related fields, based on the subclass-computed 1533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fields computed by handleComputeFields(). 1534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeWeekFields(ec); 1535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute time-related fields. These are indepent of the date and 1537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the subclass algorithm. They depend only on the local zone 1538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // wall milliseconds in day. 1539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t millisInDay = (int32_t) (localMillis - (days * kOneDay)); 1540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_MILLISECONDS_IN_DAY] = millisInDay; 1541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_MILLISECOND] = millisInDay % 1000; 1542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay /= 1000; 1543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_SECOND] = millisInDay % 60; 1544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay /= 60; 1545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_MINUTE] = millisInDay % 60; 1546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay /= 60; 1547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_HOUR_OF_DAY] = millisInDay; 1548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_AM_PM] = millisInDay / 12; // Assume AM == 0 1549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_HOUR] = millisInDay % 12; 1550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_ZONE_OFFSET] = rawOffset; 1551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_DST_OFFSET] = dstOffset; 1552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuint8_t Calendar::julianDayToDayOfWeek(double julian) 1555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If julian is negative, then julian%7 will be negative, so we adjust 1557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // accordingly. We add 1 because Julian day 0 is Monday. 1558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int8_t dayOfWeek = (int8_t) uprv_fmod(julian + 1, 7); 1559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint8_t result = (uint8_t)(dayOfWeek + ((dayOfWeek < 0) ? (7+UCAL_SUNDAY ) : UCAL_SUNDAY)); 1561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 1562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Compute the Gregorian calendar year, month, and day of month from 1566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* the given Julian day. These values are not stored in fields, but in 1567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* member variables gregorianXxx. Also compute the DAY_OF_WEEK and 1568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DOW_LOCAL fields. 1569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::computeGregorianAndDOWFields(int32_t julianDay, UErrorCode &ec) 1571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeGregorianFields(julianDay, ec); 1573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute day of week: JD 0 = Monday 1575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dow = julianDayToDayOfWeek(julianDay); 1576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_DAY_OF_WEEK,dow); 1577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Calculate 1-based localized day of week 1579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dowLocal = dow - getFirstDayOfWeek() + 1; 1580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dowLocal < 1) { 1581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal += 7; 1582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_DOW_LOCAL,dowLocal); 1584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_DOW_LOCAL] = dowLocal; 1585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Compute the Gregorian calendar year, month, and day of month from the 1589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Julian day. These values are not stored in fields, but in member 1590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* variables gregorianXxx. They are used for time zone computations and by 1591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* subclasses that are Gregorian derivatives. Subclasses may call this 1592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* method to perform a Gregorian calendar millis->fields computation. 1593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::computeGregorianFields(int32_t julianDay, UErrorCode & /* ec */) { 1595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t gregorianDayOfWeekUnused; 1596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Grego::dayToFields(julianDay - kEpochStartAsJulianDay, fGregorianYear, fGregorianMonth, fGregorianDayOfMonth, gregorianDayOfWeekUnused, fGregorianDayOfYear); 1597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 1600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Compute the fields WEEK_OF_YEAR, YEAR_WOY, WEEK_OF_MONTH, 1601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_WEEK_IN_MONTH, and DOW_LOCAL from EXTENDED_YEAR, YEAR, 1602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DAY_OF_WEEK, and DAY_OF_YEAR. The latter fields are computed by the 1603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* subclass based on the calendar system. 1604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 1605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p>The YEAR_WOY field is computed simplistically. It is equal to YEAR 1606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* most of the time, but at the year boundary it may be adjusted to YEAR-1 1607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* or YEAR+1 to reflect the overlap of a week into an adjacent year. In 1608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* this case, a simple increment or decrement is performed on YEAR, even 1609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* though this may yield an invalid YEAR value. For instance, if the YEAR 1610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* is part of a calendar system with an N-year cycle field CYCLE, then 1611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* incrementing the YEAR may involve incrementing CYCLE and setting YEAR 1612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* back to 0 or 1. This is not handled by this code, and in fact cannot be 1613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* simply handled without having subclasses define an entire parallel set of 1614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* fields for fields larger than or equal to a year. This additional 1615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* complexity is not warranted, since the intention of the YEAR_WOY field is 1616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* to support ISO 8601 notation, so it will typically be used with a 1617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* proleptic Gregorian calendar, which has no field larger than a year. 1618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 1619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::computeWeekFields(UErrorCode &ec) { 1620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(ec)) { 1621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t eyear = fFields[UCAL_EXTENDED_YEAR]; 1624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dayOfWeek = fFields[UCAL_DAY_OF_WEEK]; 1625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dayOfYear = fFields[UCAL_DAY_OF_YEAR]; 1626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // WEEK_OF_YEAR start 1628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute the week of the year. For the Gregorian calendar, valid week 1629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // numbers run from 1 to 52 or 53, depending on the year, the first day 1630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the week, and the minimal days in the first week. For other 1631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // calendars, the valid range may be different -- it depends on the year 1632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // length. Days at the start of the year may fall into the last week of 1633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the previous year; days at the end of the year may fall into the 1634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first week of the next year. ASSUME that the year length is less than 1635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 7000 days. 1636c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru int32_t yearOfWeekOfYear = eyear; 1637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t relDow = (dayOfWeek + 7 - getFirstDayOfWeek()) % 7; // 0..6 1638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t relDowJan1 = (dayOfWeek - dayOfYear + 7001 - getFirstDayOfWeek()) % 7; // 0..6 1639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t woy = (dayOfYear - 1 + relDowJan1) / 7; // 0..53 1640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - relDowJan1) >= getMinimalDaysInFirstWeek()) { 1641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++woy; 1642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Adjust for weeks at the year end that overlap into the previous or 1645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // next calendar year. 1646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (woy == 0) { 1647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We are the last week of the previous year. 1648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Check to see if we are in the last week; if so, we need 1649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to handle the case in which we are the first week of the 1650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // next year. 1651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t prevDoy = dayOfYear + handleGetYearLength(eyear - 1); 1653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru woy = weekNumber(prevDoy, dayOfWeek); 1654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru yearOfWeekOfYear--; 1655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t lastDoy = handleGetYearLength(eyear); 1657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fast check: For it to be week 1 of the next year, the DOY 1658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // must be on or after L-5, where L is yearLength(), then it 1659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // cannot possibly be week 1 of the next year: 1660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // L-5 L 1661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // doy: 359 360 361 362 363 364 365 001 1662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // dow: 1 2 3 4 5 6 7 1663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dayOfYear >= (lastDoy - 5)) { 1664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t lastRelDow = (relDow + lastDoy - dayOfYear) % 7; 1665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lastRelDow < 0) { 1666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lastRelDow += 7; 1667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) && 1669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ((dayOfYear + 7 - relDow) > lastDoy)) { 1670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru woy = 1; 1671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru yearOfWeekOfYear++; 1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_WEEK_OF_YEAR] = woy; 1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_YEAR_WOY] = yearOfWeekOfYear; 1677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // WEEK_OF_YEAR end 1678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dayOfMonth = fFields[UCAL_DAY_OF_MONTH]; 1680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek); 1681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFields[UCAL_DAY_OF_WEEK_IN_MONTH] = (dayOfMonth-1) / 7 + 1; 1682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 1683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(fFields[UCAL_DAY_OF_WEEK_IN_MONTH]==0) fprintf(stderr, "%s:%d: DOWIM %d on %g\n", 1684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__,fFields[UCAL_DAY_OF_WEEK_IN_MONTH], fTime); 1685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 1686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::weekNumber(int32_t desiredDay, int32_t dayOfPeriod, int32_t dayOfWeek) 1690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Determine the day of the week of the first day of the period 1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in question (either a year or a month). Zero represents the 1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first day of the week on this calendar. 1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7; 1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (periodStartDayOfWeek < 0) periodStartDayOfWeek += 7; 1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute the week number. Initially, ignore the first week, which 1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // may be fractional (or may not be). We add periodStartDayOfWeek in 1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // order to fill out the first week, if it is fractional. 1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t weekNo = (desiredDay + periodStartDayOfWeek - 1)/7; 1701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the first week is long enough, then count it. If 1703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the minimal days in the first week is one, or if the period start 1704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is zero, we always increment weekNo. 1705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek()) ++weekNo; 1706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return weekNo; 1708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::handleComputeFields(int32_t /* julianDay */, UErrorCode &/* status */) 1711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_MONTH, getGregorianMonth()); 1713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_DAY_OF_MONTH, getGregorianDayOfMonth()); 1714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_DAY_OF_YEAR, getGregorianDayOfYear()); 1715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t eyear = getGregorianYear(); 1716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_EXTENDED_YEAR, eyear); 1717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t era = GregorianCalendar::AD; 1718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (eyear < 1) { 1719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru era = GregorianCalendar::BC; 1720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru eyear = 1 - eyear; 1721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_ERA, era); 1723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_YEAR, eyear); 1724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 1726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::roll(EDateFields field, int32_t amount, UErrorCode& status) 1729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru roll((UCalendarDateFields)field, amount, status); 1731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) 1734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 1735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (amount == 0) { 1736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; // Nothing to do 1737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru complete(status); 1740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 1742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 1745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_MONTH: 1746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_AM_PM: 1747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MINUTE: 1748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_SECOND: 1749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECOND: 1750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECONDS_IN_DAY: 1751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_ERA: 1752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // These are the standard roll instructions. These work for all 1753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // simple cases, that is, cases in which the limits are fixed, such 1754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // as the hour, the day of the month, and the era. 1755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t min = getActualMinimum(field,status); 1757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = getActualMaximum(field,status); 1758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t gap = max - min + 1; 1759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t value = internalGet(field) + amount; 1761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value = (value - min) % gap; 1762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (value < 0) { 1763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value += gap; 1764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value += min; 1766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, value); 1768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR: 1772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR_OF_DAY: 1773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Rolling the hour is difficult on the ONSET and CEASE days of 1774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // daylight savings. For example, if the change occurs at 1775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 2 AM, we have the following progression: 1776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // ONSET: 12 Std -> 1 Std -> 3 Dst -> 4 Dst 1777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // CEASE: 12 Dst -> 1 Dst -> 1 Std -> 2 Std 1778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // To get around this problem we don't use fields; we manipulate 1779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the time in millis directly. 1780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Assume min == 0 in calculations below 1782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double start = getTimeInMillis(status); 1783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t oldHour = internalGet(field); 1784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = getMaximum(field); 1785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t newHour = (oldHour + amount) % (max + 1); 1786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (newHour < 0) { 1787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru newHour += max + 1; 1788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(start + kOneHour * (newHour - oldHour),status); 1790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MONTH: 1794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Rolling the month involves both pinning the final value 1795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and adjusting the DAY_OF_MONTH if necessary. We only adjust the 1796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // DAY_OF_MONTH if, after updating the MONTH field, it is illegal. 1797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // E.g., <jan31>.roll(MONTH, 1) -> <feb28> or <feb29>. 1798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = getActualMaximum(UCAL_MONTH, status); 1800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t mon = (internalGet(UCAL_MONTH) + amount) % (max+1); 1801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (mon < 0) { 1803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mon += (max + 1); 1804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MONTH, mon); 1806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Keep the day of month in range. We don't want to spill over 1808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // into the next month; e.g., we don't want jan31 + 1 mo -> feb31 -> 1809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // mar3. 1810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pinField(UCAL_DAY_OF_MONTH,status); 1811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_YEAR: 1815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_YEAR_WOY: 181654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius { 181754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // * If era==0 and years go backwards in time, change sign of amount. 181854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // * Until we have new API per #9393, we temporarily hardcode knowledge of 181954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // which calendars have era 0 years that go backwards. 182054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius UBool era0WithYearsThatGoBackwards = FALSE; 182154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t era = get(UCAL_ERA, status); 182254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (era == 0) { 182354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char * calType = getType(); 182454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if ( uprv_strcmp(calType,"gregorian")==0 || uprv_strcmp(calType,"roc")==0 || uprv_strcmp(calType,"coptic")==0 ) { 182554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius amount = -amount; 182654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius era0WithYearsThatGoBackwards = TRUE; 182754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 182854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 182954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t newYear = internalGet(field) + amount; 183054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (era > 0 || newYear >= 1) { 183154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t maxYear = getActualMaximum(field, status); 183254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (maxYear < 32768) { 183354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // this era has real bounds, roll should wrap years 183454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (newYear < 1) { 183554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius newYear = maxYear - ((-newYear) % maxYear); 183654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else if (newYear > maxYear) { 183754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius newYear = ((newYear - 1) % maxYear) + 1; 183854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 183954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // else era is unbounded, just pin low year instead of wrapping 184054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else if (newYear < 1) { 184154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius newYear = 1; 184254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 184354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // else we are in era 0 with newYear < 1; 184454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // calendars with years that go backwards must pin the year value at 0, 184554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // other calendars can have years < 0 in era 0 184654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else if (era0WithYearsThatGoBackwards) { 184754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius newYear = 1; 184854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 184954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius set(field, newYear); 185054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pinField(UCAL_MONTH,status); 185154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius pinField(UCAL_DAY_OF_MONTH,status); 185254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius return; 185354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 185454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 1855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_EXTENDED_YEAR: 1856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Rolling the year can involve pinning the DAY_OF_MONTH. 1857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, internalGet(field) + amount); 1858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pinField(UCAL_MONTH,status); 1859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pinField(UCAL_DAY_OF_MONTH,status); 1860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_MONTH: 1863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This is tricky, because during the roll we may have to shift 1865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to a different day of the week. For example: 1866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // s m t w r f s 1868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1 2 3 4 5 1869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 6 7 8 9 10 11 12 1870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // When rolling from the 6th or 7th back one week, we go to the 1872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1st (assuming that the first partial week counts). The same 1873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // thing happens at the end of the month. 1874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The other tricky thing is that we have to figure out whether 1876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the first partial week actually counts or not, based on the 1877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // minimal first days in the week. And we have to use the 1878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // correct first day of the week to delineate the week 1879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // boundaries. 1880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Here's our algorithm. First, we find the real boundaries of 1882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the month. Then we discard the first partial week if it 1883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // doesn't count in this locale. Then we fill in the ends with 1884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // phantom days, so that the first partial week and the last 1885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // partial week are full weeks. We then have a nice square 1886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // block of weeks. We do the usual rolling within this block, 1887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // as is done elsewhere in this method. If we wind up on one of 1888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the phantom days that we added, we recognize this and pin to 1889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the first or the last day of the month. Easy, eh? 1890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Normalize the DAY_OF_WEEK so that 0 is the first day of the week 1892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in this locale. We have dow in 0..6. 1893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek(); 1894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dow < 0) dow += 7; 1895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the day of the week (normalized for locale) for the first 1897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the month. 1898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t fdm = (dow - internalGet(UCAL_DAY_OF_MONTH) + 1) % 7; 1899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fdm < 0) fdm += 7; 1900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the first day of the first full week of the month, 1902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // including phantom days, if any. Figure out if the first week 1903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // counts or not; if it counts, then fill in phantom days. If 1904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // not, advance to the first real full week (skip the partial week). 1905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start; 1906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - fdm) < getMinimalDaysInFirstWeek()) 1907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start = 8 - fdm; // Skip the first partial week 1908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else 1909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start = 1 - fdm; // This may be zero or negative 1910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the day of the week (normalized for locale) for the last 1912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // day of the month. 1913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t monthLen = getActualMaximum(UCAL_DAY_OF_MONTH, status); 1914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t ldm = (monthLen - internalGet(UCAL_DAY_OF_MONTH) + dow) % 7; 1915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here. 1916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the limit day for the blocked-off rectangular month; that 1918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is, the day which is one past the last day of the month, 1919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // after the month has already been filled in with phantom days 1920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to fill out the last week. This day has a normalized DOW of 0. 1921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit = monthLen + 7 - ldm; 1922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now roll between start and (limit - 1). 1924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t gap = limit - start; 1925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t day_of_month = (internalGet(UCAL_DAY_OF_MONTH) + amount*7 - 1926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start) % gap; 1927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_month < 0) day_of_month += gap; 1928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day_of_month += start; 1929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Finally, pin to the real start and end of the month. 1931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_month < 1) day_of_month = 1; 1932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_month > monthLen) day_of_month = monthLen; 1933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set the DAY_OF_MONTH. We rely on the fact that this field 1935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // takes precedence over everything else (since all other fields 1936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // are also set at this point). If this fact changes (if the 1937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // disambiguation algorithm changes) then we will have to unset 1938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the appropriate fields here so that DAY_OF_MONTH is attended 1939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to. 1940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DAY_OF_MONTH, day_of_month); 1941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_YEAR: 1944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 1945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This follows the outline of WEEK_OF_MONTH, except it applies 1946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to the whole year. Please see the comment for WEEK_OF_MONTH 1947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // for general notes. 1948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Normalize the DAY_OF_WEEK so that 0 is the first day of the week 1950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in this locale. We have dow in 0..6. 1951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek(); 1952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dow < 0) dow += 7; 1953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the day of the week (normalized for locale) for the first 1955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // of the year. 1956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t fdy = (dow - internalGet(UCAL_DAY_OF_YEAR) + 1) % 7; 1957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fdy < 0) fdy += 7; 1958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the first day of the first full week of the year, 1960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // including phantom days, if any. Figure out if the first week 1961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // counts or not; if it counts, then fill in phantom days. If 1962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // not, advance to the first real full week (skip the partial week). 1963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t start; 1964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - fdy) < getMinimalDaysInFirstWeek()) 1965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start = 8 - fdy; // Skip the first partial week 1966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else 1967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start = 1 - fdy; // This may be zero or negative 1968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the day of the week (normalized for locale) for the last 1970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // day of the year. 1971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t yearLen = getActualMaximum(UCAL_DAY_OF_YEAR,status); 1972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t ldy = (yearLen - internalGet(UCAL_DAY_OF_YEAR) + dow) % 7; 1973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We know yearLen >= DAY_OF_YEAR so we skip the += 7 step here. 1974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the limit day for the blocked-off rectangular year; that 1976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is, the day which is one past the last day of the year, 1977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // after the year has already been filled in with phantom days 1978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to fill out the last week. This day has a normalized DOW of 0. 1979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t limit = yearLen + 7 - ldy; 1980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now roll between start and (limit - 1). 1982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t gap = limit - start; 1983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t day_of_year = (internalGet(UCAL_DAY_OF_YEAR) + amount*7 - 1984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru start) % gap; 1985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_year < 0) day_of_year += gap; 1986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day_of_year += start; 1987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Finally, pin to the real start and end of the month. 1989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_year < 1) day_of_year = 1; 1990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (day_of_year > yearLen) day_of_year = yearLen; 1991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Make sure that the year and day of year are attended to by 1993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // clearing other fields which would normally take precedence. 1994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If the disambiguation algorithm is changed, this section will 1995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // have to be updated as well. 1996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DAY_OF_YEAR, day_of_year); 1997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru clear(UCAL_MONTH); 1998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_YEAR: 2001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Roll the day of year using millis. Compute the millis for 2003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the start of the year, and get the length of the year. 2004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double delta = amount * kOneDay; // Scale up from days to millis 2005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double min2 = internalGet(UCAL_DAY_OF_YEAR)-1; 2006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min2 *= kOneDay; 2007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min2 = internalGetTime() - min2; 2008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // double min2 = internalGetTime() - (internalGet(UCAL_DAY_OF_YEAR) - 1.0) * kOneDay; 2010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double newtime; 2011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double yearLength = getActualMaximum(UCAL_DAY_OF_YEAR,status); 2013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double oneYear = yearLength; 2014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru oneYear *= kOneDay; 2015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru newtime = uprv_fmod((internalGetTime() + delta - min2), oneYear); 2016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (newtime < 0) newtime += oneYear; 2017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(newtime + min2, status); 2018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK: 2021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DOW_LOCAL: 2022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Roll the day of week using millis. Compute the millis for 2024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the start of the week, using the first day of week setting. 2025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Restrict the millis to [start, start+7days). 2026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double delta = amount * kOneDay; // Scale up from days to millis 2027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute the number of days before the current day in this 2028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // week. This will be a value 0..6. 2029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t leadDays = internalGet(field); 2030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru leadDays -= (field == UCAL_DAY_OF_WEEK) ? getFirstDayOfWeek() : 1; 2031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (leadDays < 0) leadDays += 7; 2032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double min2 = internalGetTime() - leadDays * kOneDay; 2033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double newtime = uprv_fmod((internalGetTime() + delta - min2), kOneWeek); 2034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (newtime < 0) newtime += kOneWeek; 2035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(newtime + min2, status); 2036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK_IN_MONTH: 2039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Roll the day of week in the month using millis. Determine 2041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the first day of the week in the month, and then the last, 2042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // and then roll within that range. 2043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double delta = amount * kOneWeek; // Scale up from weeks to millis 2044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the number of same days of the week before this one 2045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in this month. 2046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t preWeeks = (internalGet(UCAL_DAY_OF_MONTH) - 1) / 7; 2047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the number of same days of the week after this one 2048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in this month. 2049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t postWeeks = (getActualMaximum(UCAL_DAY_OF_MONTH,status) - 2050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalGet(UCAL_DAY_OF_MONTH)) / 7; 2051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // From these compute the min and gap millis for rolling. 2052b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double min2 = internalGetTime() - preWeeks * kOneWeek; 2053b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double gap2 = kOneWeek * (preWeeks + postWeeks + 1); // Must add 1! 2054b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Roll within this range 2055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double newtime = uprv_fmod((internalGetTime() + delta - min2), gap2); 2056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (newtime < 0) newtime += gap2; 2057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(newtime + min2, status); 2058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2060b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_JULIAN_DAY: 2061b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, internalGet(field) + amount); 2062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 2064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Other fields cannot be rolled by this method 2065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because of roll on non-rollable field %s\n", 2067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__,fldName(field)); 2068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 2070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::add(EDateFields field, int32_t amount, UErrorCode& status) 2074b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2075b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar::add((UCalendarDateFields)field, amount, status); 2076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status) 2080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (amount == 0) { 2082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; // Do nothing! 2083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We handle most fields in the same way. The algorithm is to add 2086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // a computed amount of millis to the current millis. The only 2087103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // wrinkle is with DST (and/or a change to the zone's UTC offset, which 2088103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // we'll include with DST) -- for some fields, like the DAY_OF_MONTH, 2089fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // we don't want the wall time to shift due to changes in DST. If the 2090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // result of the add operation is to move from DST to Standard, or 2091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // vice versa, we need to adjust by an hour forward or back, 2092fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // respectively. For such fields we set keepWallTimeInvariant to TRUE. 2093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We only adjust the DST for fields larger than an hour. For 2095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fields smaller than an hour, we cannot adjust for DST without 2096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // causing problems. for instance, if you add one hour to April 5, 2097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an 2098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // illegal value), but then the adjustment sees the change and 2099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // compensates by subtracting an hour. As a result the time 2100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // doesn't advance at all. 2101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For some fields larger than a day, such as a UCAL_MONTH, we pin the 2103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // UCAL_DAY_OF_MONTH. This allows <March 31>.add(UCAL_MONTH, 1) to be 2104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // <April 30>, rather than <April 31> => <May 1>. 2105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double delta = amount; // delta in ms 2107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool keepWallTimeInvariant = TRUE; 2108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 2110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_ERA: 2111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, get(field, status) + amount); 2112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pinField(UCAL_ERA, status); 2113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_YEAR: 2116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_YEAR_WOY: 211754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius { 211854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // * If era=0 and years go backwards in time, change sign of amount. 211954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // * Until we have new API per #9393, we temporarily hardcode knowledge of 212054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // which calendars have era 0 years that go backwards. 212154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // * Note that for UCAL_YEAR (but not UCAL_YEAR_WOY) we could instead handle 212254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // this by applying the amount to the UCAL_EXTENDED_YEAR field; but since 212354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // we would still need to handle UCAL_YEAR_WOY as below, might as well 212454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // also handle UCAL_YEAR the same way. 212554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t era = get(UCAL_ERA, status); 212654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (era == 0) { 212754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius const char * calType = getType(); 212854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if ( uprv_strcmp(calType,"gregorian")==0 || uprv_strcmp(calType,"roc")==0 || uprv_strcmp(calType,"coptic")==0 ) { 212954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius amount = -amount; 213054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 213154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 213254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 213354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // Fall through into normal handling 213454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius case UCAL_EXTENDED_YEAR: 2135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MONTH: 2136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 2137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool oldLenient = isLenient(); 2138103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius setLenient(TRUE); 2139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, get(field, status) + amount); 2140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pinField(UCAL_DAY_OF_MONTH, status); 2141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if(oldLenient==FALSE) { 2142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius complete(status); /* force recalculate */ 2143103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius setLenient(oldLenient); 2144103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2145103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2146103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return; 2147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_YEAR: 2149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_MONTH: 2150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK_IN_MONTH: 2151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= kOneWeek; 2152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_AM_PM: 2155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= 12 * kOneHour; 2156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_MONTH: 2159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_YEAR: 2160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK: 2161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DOW_LOCAL: 2162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_JULIAN_DAY: 2163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= kOneDay; 2164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR_OF_DAY: 2167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR: 2168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= kOneHour; 2169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius keepWallTimeInvariant = FALSE; 2170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MINUTE: 2173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= kOneMinute; 2174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius keepWallTimeInvariant = FALSE; 2175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_SECOND: 2178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delta *= kOneSecond; 2179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius keepWallTimeInvariant = FALSE; 2180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECOND: 2183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECONDS_IN_DAY: 2184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius keepWallTimeInvariant = FALSE; 2185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 2188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s not addable", 2190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__, fldName(field)); 2191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 2193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // throw new IllegalArgumentException("Calendar.add(" + fieldName(field) + 2195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // ") not supported"); 2196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // In order to keep the wall time invariant (for fields where this is 2199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // appropriate), check the combined DST & ZONE offset before and 2200103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // after the add() operation. If it changes, then adjust the millis 2201103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // to compensate. 2202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t prevOffset = 0; 2203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t prevWallTime = 0; 2204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (keepWallTimeInvariant) { 2205103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius prevOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); 2206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius prevWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); 2207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(getTimeInMillis(status) + delta, status); 2210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (keepWallTimeInvariant) { 2212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); 2213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newWallTime != prevWallTime) { 2214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // There is at least one zone transition between the base 2215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // time and the result time. As the result, wall time has 2216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // changed. 2217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate t = internalGetTime(); 2218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t newOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); 2219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newOffset != prevOffset) { 2220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // When the difference of the previous UTC offset and 2221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // the new UTC offset exceeds 1 full day, we do not want 2222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // to roll over/back the date. For now, this only happens 2223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452. 2224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t adjAmount = prevOffset - newOffset; 2225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-adjAmount % (int32_t)kOneDay); 2226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (adjAmount != 0) { 2227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius setTimeInMillis(t + adjAmount, status); 2228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status); 2229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 2230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (newWallTime != prevWallTime) { 2231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // The result wall time or adjusted wall time was shifted because 2232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // the target wall time does not exist on the result date. 2233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (fSkippedWallTime) { 2234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCAL_WALLTIME_FIRST: 2235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (adjAmount > 0) { 2236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius setTimeInMillis(t, status); 2237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 2238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 2239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCAL_WALLTIME_LAST: 2240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (adjAmount < 0) { 2241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius setTimeInMillis(t, status); 2242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 2243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 2244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCAL_WALLTIME_NEXT_VALID: 2245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate tmpT = adjAmount > 0 ? internalGetTime() : t; 2246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate immediatePrevTrans; 2247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool hasTransition = getImmediatePreviousZoneTransition(tmpT, &immediatePrevTrans, status); 2248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_SUCCESS(status) && hasTransition) { 2249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius setTimeInMillis(immediatePrevTrans, status); 2250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 2251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 2252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 225354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 2254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::fieldDifference(UDate when, EDateFields field, UErrorCode& status) { 2261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fieldDifference(when, (UCalendarDateFields) field, status); 2262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::fieldDifference(UDate targetMs, UCalendarDateFields field, UErrorCode& ec) { 2265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(ec)) return 0; 2266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t min = 0; 2267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double startMs = getTimeInMillis(ec); 2268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Always add from the start millis. This accomodates 2269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // operations like adding years from February 29, 2000 up to 2270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // February 29, 2004. If 1, 1, 1, 1 is added to the year 2271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // field, the DOM gets pinned to 28 and stays there, giving an 2272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // incorrect DOM difference of 1. We have to add 1, reset, 2, 2273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // reset, 3, reset, 4. 2274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (startMs < targetMs) { 2275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = 1; 2276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a value that is too large 2277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (U_SUCCESS(ec)) { 2278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(startMs, ec); 2279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru add(field, max, ec); 2280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double ms = getTimeInMillis(ec); 2281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ms == targetMs) { 2282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return max; 2283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ms > targetMs) { 2284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 228554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else if (max < INT32_MAX) { 2286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho min = max; 2287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru max <<= 1; 2288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (max < 0) { 228954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius max = INT32_MAX; 229054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 229154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } else { 229254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius // Field difference too large to fit into int32_t 2293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 229454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s's max too large for int32_t\n", 229554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius __FILE__, __LINE__, fldName(field)); 2296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 229754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius ec = U_ILLEGAL_ARGUMENT_ERROR; 2298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do a binary search 2301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while ((max - min) > 1 && U_SUCCESS(ec)) { 230254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t t = min + (max - min)/2; // make sure intermediate values don't exceed INT32_MAX 2303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(startMs, ec); 2304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru add(field, t, ec); 2305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double ms = getTimeInMillis(ec); 2306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ms == targetMs) { 2307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return t; 2308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ms > targetMs) { 2309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru max = t; 2310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = t; 2312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (startMs > targetMs) { 2315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t max = -1; 2316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find a value that is too small 2317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (U_SUCCESS(ec)) { 2318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(startMs, ec); 2319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru add(field, max, ec); 2320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double ms = getTimeInMillis(ec); 2321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ms == targetMs) { 2322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return max; 2323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ms < targetMs) { 2324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho min = max; 2327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru max <<= 1; 2328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (max == 0) { 2329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Field difference too large to fit into int32_t 2330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s's max too large for int32_t\n", 2332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__, fldName(field)); 2333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ec = U_ILLEGAL_ARGUMENT_ERROR; 2335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do a binary search 2339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while ((min - max) > 1 && U_SUCCESS(ec)) { 234054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius int32_t t = min + (max - min)/2; // make sure intermediate values don't exceed INT32_MAX 2341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(startMs, ec); 2342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru add(field, t, ec); 2343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double ms = getTimeInMillis(ec); 2344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (ms == targetMs) { 2345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return t; 2346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (ms < targetMs) { 2347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru max = t; 2348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 2349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = t; 2350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Set calendar to end point 2354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru setTimeInMillis(startMs, ec); 2355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru add(field, min, ec); 2356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Test for buffer overflows */ 2358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(ec)) { 2359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return min; 2362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 2367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::adoptTimeZone(TimeZone* zone) 2368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do nothing if passed-in zone is NULL 2370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (zone == NULL) return; 2371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fZone should always be non-null 2373f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius delete fZone; 2374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fZone = zone; 2375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if the zone changes, we need to recompute the time fields 2377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = FALSE; 2378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 2382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::setTimeZone(const TimeZone& zone) 2383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru adoptTimeZone(zone.clone()); 2385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst TimeZone& 2390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getTimeZone() const 2391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2392f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius U_ASSERT(fZone != NULL); 2393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return *fZone; 2394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone* 2399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::orphanTimeZone() 2400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we let go of the time zone; the new time zone is the system default time zone 2402f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius TimeZone *defaultZone = TimeZone::createDefault(); 2403f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius if (defaultZone == NULL) { 2404f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // No error handling available. Must keep fZone non-NULL, there are many unchecked uses. 2405f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius return NULL; 2406f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius } 2407f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius TimeZone *z = fZone; 2408f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius fZone = defaultZone; 2409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return z; 2410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 2415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::setLenient(UBool lenient) 2416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fLenient = lenient; 2418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool 2423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::isLenient() const 2424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fLenient; 2426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 2431103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendar::setRepeatedWallTimeOption(UCalendarWallTimeOption option) 2432103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{ 2433103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (option == UCAL_WALLTIME_LAST || option == UCAL_WALLTIME_FIRST) { 2434103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fRepeatedWallTime = option; 2435103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2436103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 2437103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2438103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// ------------------------------------- 2439103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2440103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUCalendarWallTimeOption 2441103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendar::getRepeatedWallTimeOption(void) const 2442103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{ 2443103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fRepeatedWallTime; 2444103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 2445103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2446103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// ------------------------------------- 2447103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2448103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusvoid 2449103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendar::setSkippedWallTimeOption(UCalendarWallTimeOption option) 2450103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{ 2451103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fSkippedWallTime = option; 2452103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 2453103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// ------------------------------------- 2455103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2456103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUCalendarWallTimeOption 2457103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendar::getSkippedWallTimeOption(void) const 2458103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{ 2459103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fSkippedWallTime; 2460103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 2461103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2462103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// ------------------------------------- 2463103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2464103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusvoid 2465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::setFirstDayOfWeek(UCalendarDaysOfWeek value) 2466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fFirstDayOfWeek != value && 2468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value >= UCAL_SUNDAY && value <= UCAL_SATURDAY) { 2469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFirstDayOfWeek = value; 2470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = FALSE; 2471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::EDaysOfWeek 2477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getFirstDayOfWeek() const 2478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (Calendar::EDaysOfWeek)fFirstDayOfWeek; 2480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUCalendarDaysOfWeek 2483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getFirstDayOfWeek(UErrorCode & /*status*/) const 2484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fFirstDayOfWeek; 2486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 2490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::setMinimalDaysInFirstWeek(uint8_t value) 2491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Values less than 1 have the same effect as 1; values greater 2493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // than 7 have the same effect as 7. However, we normalize values 2494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // so operator== and so forth work. 2495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (value < 1) { 2496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value = 1; 2497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if (value > 7) { 2498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru value = 7; 2499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fMinimalDaysInFirstWeek != value) { 2501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fMinimalDaysInFirstWeek = value; 2502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = FALSE; 2503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuint8_t 2509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getMinimalDaysInFirstWeek() const 2510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fMinimalDaysInFirstWeek; 2512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 251450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// ------------------------------------- 251550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// weekend functions, just dummy implementations for now (for API freeze) 251650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 251750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUCalendarWeekdayType 251850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::getDayOfWeekType(UCalendarDaysOfWeek dayOfWeek, UErrorCode &status) const 251950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 252050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 252150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return UCAL_WEEKDAY; 252250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 252350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek < UCAL_SUNDAY || dayOfWeek > UCAL_SATURDAY) { 252450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ILLEGAL_ARGUMENT_ERROR; 252550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return UCAL_WEEKDAY; 252650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 2527fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (fWeekendOnset == fWeekendCease) { 2528fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (dayOfWeek != fWeekendOnset) 2529fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return UCAL_WEEKDAY; 2530fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ONSET; 2531fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 253250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fWeekendOnset < fWeekendCease) { 253350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek < fWeekendOnset || dayOfWeek > fWeekendCease) { 253450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return UCAL_WEEKDAY; 253550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 253650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 253750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek > fWeekendCease && dayOfWeek < fWeekendOnset) { 253850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return UCAL_WEEKDAY; 253950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 254050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 254150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek == fWeekendOnset) { 254250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ONSET; 254350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 254450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek == fWeekendCease) { 254559d709d503bab6e2b61931737e662dd293b40578ccornelius return (fWeekendCeaseMillis >= 86400000) ? UCAL_WEEKEND : UCAL_WEEKEND_CEASE; 254650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 254750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return UCAL_WEEKEND; 254850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 254950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 255050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t 255150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::getWeekendTransition(UCalendarDaysOfWeek dayOfWeek, UErrorCode &status) const 255250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 255350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 255450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 255550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 255650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dayOfWeek == fWeekendOnset) { 255750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fWeekendOnsetMillis; 255850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (dayOfWeek == fWeekendCease) { 255950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return fWeekendCeaseMillis; 256050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 256150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ILLEGAL_ARGUMENT_ERROR; 256250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 256350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 256450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 256550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool 256650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::isWeekend(UDate date, UErrorCode &status) const 256750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 256850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 256950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 257050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 257150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // clone the calendar so we don't mess with the real one. 257250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho Calendar *work = (Calendar*)this->clone(); 257350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (work == NULL) { 257450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 257550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 257650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 257750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool result = FALSE; 257850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho work->setTime(date, status); 257950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 258050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = work->isWeekend(); 258150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 258250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete work; 258350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 258450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 258550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 258650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUBool 258750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::isWeekend(void) const 258850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho{ 258950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 259050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UCalendarDaysOfWeek dayOfWeek = (UCalendarDaysOfWeek)get(UCAL_DAY_OF_WEEK, status); 259150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UCalendarWeekdayType dayType = getDayOfWeekType(dayOfWeek, status); 259250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 259350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (dayType) { 259450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case UCAL_WEEKDAY: 259550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 259650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case UCAL_WEEKEND: 259750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return TRUE; 259850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case UCAL_WEEKEND_ONSET: 259950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case UCAL_WEEKEND_CEASE: 260050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Use internalGet() because the above call to get() populated all fields. 260150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 260250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t millisInDay = internalGet(UCAL_MILLISECONDS_IN_DAY); 260350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t transitionMillis = getWeekendTransition(dayOfWeek, status); 260450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 260550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (dayType == UCAL_WEEKEND_ONSET)? 260650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (millisInDay >= transitionMillis): 260750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (millisInDay < transitionMillis); 260850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 260950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // else fall through, return FALSE 261050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 261150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 261250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 261350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 261450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 261550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return FALSE; 261650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 261750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 2618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- limits 2619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getMinimum(EDateFields field) const { 2622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit((UCalendarDateFields) field,UCAL_LIMIT_MINIMUM); 2623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getMinimum(UCalendarDateFields field) const 2627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit(field,UCAL_LIMIT_MINIMUM); 2629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getMaximum(EDateFields field) const 2634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit((UCalendarDateFields) field,UCAL_LIMIT_MAXIMUM); 2636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getMaximum(UCalendarDateFields field) const 2640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit(field,UCAL_LIMIT_MAXIMUM); 2642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getGreatestMinimum(EDateFields field) const 2647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit((UCalendarDateFields)field,UCAL_LIMIT_GREATEST_MINIMUM); 2649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getGreatestMinimum(UCalendarDateFields field) const 2653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit(field,UCAL_LIMIT_GREATEST_MINIMUM); 2655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getLeastMaximum(EDateFields field) const 2660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit((UCalendarDateFields) field,UCAL_LIMIT_LEAST_MAXIMUM); 2662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getLeastMaximum(UCalendarDateFields field) const 2666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getLimit( field,UCAL_LIMIT_LEAST_MAXIMUM); 2668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getActualMinimum(EDateFields field, UErrorCode& status) const 2673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return getActualMinimum((UCalendarDateFields) field, status); 2675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::getLimit(UCalendarDateFields field, ELimitType limitType) const { 2678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 2679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK: 2680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_AM_PM: 2681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR: 2682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR_OF_DAY: 2683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MINUTE: 2684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_SECOND: 2685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECOND: 2686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_ZONE_OFFSET: 2687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DST_OFFSET: 2688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DOW_LOCAL: 2689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_JULIAN_DAY: 2690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECONDS_IN_DAY: 2691c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru case UCAL_IS_LEAP_MONTH: 2692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return kCalendarLimits[field][limitType]; 2693c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 2694c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru case UCAL_WEEK_OF_MONTH: 2695c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru { 2696c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru int32_t limit; 2697c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (limitType == UCAL_LIMIT_MINIMUM) { 2698c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru limit = getMinimalDaysInFirstWeek() == 1 ? 1 : 0; 2699c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else if (limitType == UCAL_LIMIT_GREATEST_MINIMUM) { 2700c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru limit = 1; 2701c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else { 2702c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru int32_t minDaysInFirst = getMinimalDaysInFirstWeek(); 2703c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru int32_t daysInMonth = handleGetLimit(UCAL_DAY_OF_MONTH, limitType); 2704c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (limitType == UCAL_LIMIT_LEAST_MAXIMUM) { 2705c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru limit = (daysInMonth + (7 - minDaysInFirst)) / 7; 2706c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else { // limitType == UCAL_LIMIT_MAXIMUM 2707c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru limit = (daysInMonth + 6 + (7 - minDaysInFirst)) / 7; 2708c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 2709c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 2710c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru return limit; 2711c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 2712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 2713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return handleGetLimit(field, limitType); 2714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 2719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getActualMinimum(UCalendarDateFields field, UErrorCode& status) const 2720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t fieldValue = getGreatestMinimum(field); 2722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t endValue = getMinimum(field); 2723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if we know that the minimum value is always the same, just return it 2725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fieldValue == endValue) { 2726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return fieldValue; 2727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // clone the calendar so we don't mess with the real one, and set it to 2730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // accept anything for the field values 2731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar *work = (Calendar*)this->clone(); 2732c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (work == NULL) { 2733c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 2734c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru return 0; 2735c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 2736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru work->setLenient(TRUE); 2737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // now try each value from getLeastMaximum() to getMaximum() one by one until 2739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we get a value that normalizes to another value. The last value that 2740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // normalizes to itself is the actual minimum for the current date 2741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t result = fieldValue; 2742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru do { 2744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru work->set(field, fieldValue); 2745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (work->get(field, status) != fieldValue) { 2746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else { 2749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = fieldValue; 2750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fieldValue--; 2751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } while (fieldValue >= endValue); 2753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete work; 2755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Test for buffer overflows */ 2757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) { 2758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 2759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 2761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 2764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 2768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Ensure that each field is within its valid range by calling {@link 2769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* #validateField(int)} on each field that has been set. This method 2770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* should only be called if this calendar is not lenient. 2771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @see #isLenient 2772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @see #validateField(int) 2773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 2774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::validateFields(UErrorCode &status) { 2775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t field = 0; U_SUCCESS(status) && (field < UCAL_FIELD_COUNT); field++) { 2776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fStamp[field] >= kMinimumUserStamp) { 2777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateField((UCalendarDateFields)field, status); 2778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 2783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Validate a single field of this calendar. Subclasses should 2784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* override this method to validate any calendar-specific fields. 2785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Generic fields can be handled by 2786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <code>Calendar.validateField()</code>. 2787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @see #validateField(int, int, int) 2788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 2789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::validateField(UCalendarDateFields field, UErrorCode &status) { 2790b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t y; 2791b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 2792b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_MONTH: 2793b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru y = handleGetExtendedYear(); 2794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateField(field, 1, handleGetMonthLength(y, internalGet(UCAL_MONTH)), status); 2795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_YEAR: 2797b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru y = handleGetExtendedYear(); 2798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateField(field, 1, handleGetYearLength(y), status); 2799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2800b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK_IN_MONTH: 2801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (internalGet(field) == 0) { 2802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2803b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because DOW in month cannot be 0\n", 2804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__); 2805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; // "DAY_OF_WEEK_IN_MONTH cannot be zero" 2807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateField(field, getMinimum(field), getMaximum(field), status); 2810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 2812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateField(field, getMinimum(field), getMaximum(field), status); 2813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 2814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 2818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Validate a single field of this calendar given its minimum and 2819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* maximum allowed value. If the field is out of range, throw a 2820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* descriptive <code>IllegalArgumentException</code>. Subclasses may 2821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* use this method in their implementation of {@link 2822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* #validateField(int)}. 2823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 2824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::validateField(UCalendarDateFields field, int32_t min, int32_t max, UErrorCode& status) 2825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t value = fFields[field]; 2827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (value < min || value > max) { 2828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: ILLEGAL ARG because of field %s out of range %d..%d at %d\n", 2830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__,fldName(field),min,max,value); 2831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_ILLEGAL_ARGUMENT_ERROR; 2833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------- 2838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UFieldResolutionTable* Calendar::getFieldResolutionTable() const { 2840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return kDatePrecedence; 2841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUCalendarDateFields Calendar::newerField(UCalendarDateFields defaultField, UCalendarDateFields alternateField) const 2845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fStamp[alternateField] > fStamp[defaultField]) { 2847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return alternateField; 2848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return defaultField; 2850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUCalendarDateFields Calendar::resolveFields(const UFieldResolutionTable* precedenceTable) { 2853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bestField = UCAL_FIELD_COUNT; 2854103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t tempBestField; 2855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t g=0; precedenceTable[g][0][0] != -1 && (bestField == UCAL_FIELD_COUNT); ++g) { 2856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bestStamp = kUnset; 2857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t l=0; precedenceTable[g][l][0] != -1; ++l) { 2858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t lineStamp = kUnset; 2859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Skip over first entry if it is negative 2860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (int32_t i=((precedenceTable[g][l][0]>=kResolveRemap)?1:0); precedenceTable[g][l][i]!=-1; ++i) { 2861103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(precedenceTable[g][l][i] < UCAL_FIELD_COUNT); 2862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t s = fStamp[precedenceTable[g][l][i]]; 2863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If any field is unset then don't use this line 2864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (s == kUnset) { 2865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru goto linesInGroup; 2866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(s > lineStamp) { 2867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru lineStamp = s; 2868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Record new maximum stamp & field no. 2871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (lineStamp > bestStamp) { 2872103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tempBestField = precedenceTable[g][l][0]; // First field refers to entire line 2873103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (tempBestField >= kResolveRemap) { 2874103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tempBestField &= (kResolveRemap-1); 2875103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // This check is needed to resolve some issues with UCAL_YEAR precedence mapping 2876103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (tempBestField != UCAL_DATE || (fStamp[UCAL_WEEK_OF_MONTH] < fStamp[tempBestField])) { 2877103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius bestField = tempBestField; 2878103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2879103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 2880103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius bestField = tempBestField; 2881103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2882103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 2883103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (bestField == tempBestField) { 2884103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius bestStamp = lineStamp; 2885103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerulinesInGroup: 2888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ; 2889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2891103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return (UCalendarDateFields)bestField; 2892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 2893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UFieldResolutionTable Calendar::kDatePrecedence[] = 2895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_MONTH, kResolveSTOP }, 2898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_YEAR, UCAL_DAY_OF_WEEK, kResolveSTOP }, 2899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP }, 2900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP }, 2901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_YEAR, UCAL_DOW_LOCAL, kResolveSTOP }, 2902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_MONTH, UCAL_DOW_LOCAL, kResolveSTOP }, 2903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP }, 2904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_YEAR, kResolveSTOP }, 2905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveRemap | UCAL_DAY_OF_MONTH, UCAL_YEAR, kResolveSTOP }, // if YEAR is set over YEAR_WOY use DAY_OF_MONTH 2906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveRemap | UCAL_WEEK_OF_YEAR, UCAL_YEAR_WOY, kResolveSTOP }, // if YEAR_WOY is set, calc based on WEEK_OF_YEAR 2907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveSTOP } 2908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }, 2909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_YEAR, kResolveSTOP }, 2911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_WEEK_OF_MONTH, kResolveSTOP }, 2912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_WEEK_IN_MONTH, kResolveSTOP }, 2913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP }, 2914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP }, 2915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveSTOP } 2916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }, 2917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {{kResolveSTOP}} 2918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UFieldResolutionTable Calendar::kDOWPrecedence[] = 2922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DAY_OF_WEEK,kResolveSTOP, kResolveSTOP }, 2925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_DOW_LOCAL,kResolveSTOP, kResolveSTOP }, 2926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {kResolveSTOP} 2927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }, 2928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {{kResolveSTOP}} 2929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// precedence for calculating a year 2932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UFieldResolutionTable Calendar::kYearPrecedence[] = 2933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 2934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 2935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_YEAR, kResolveSTOP }, 2936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_EXTENDED_YEAR, kResolveSTOP }, 2937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { UCAL_YEAR_WOY, UCAL_WEEK_OF_YEAR, kResolveSTOP }, // YEAR_WOY is useless without WEEK_OF_YEAR 2938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { kResolveSTOP } 2939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru }, 2940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {{kResolveSTOP}} 2941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 2942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------- 2945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::computeTime(UErrorCode& status) { 2948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (!isLenient()) { 2949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru validateFields(status); 2950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 2951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 2952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 2954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute the Julian day 2956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t julianDay = computeJulianDay(); 2957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru double millis = Grego::julianDayToMillis(julianDay); 2959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 2961b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // int32_t julianInsanityCheck = (int32_t)ClockMath::floorDivide(millis, kOneDay); 2962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // julianInsanityCheck += kEpochStartAsJulianDay; 2963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if(1 || julianInsanityCheck != julianDay) { 2964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // fprintf(stderr, "%s:%d- D'oh- computed jules %d, to mills (%s)%.lf, recomputed %d\n", 2965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // __FILE__, __LINE__, julianDay, millis<0.0?"NEG":"", millis, julianInsanityCheck); 2966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // } 2967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 2968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t millisInDay; 2970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We only use MILLISECONDS_IN_DAY if it has been set by the user. 2972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This makes it possible for the caller to set the calendar to a 2973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // time and call clear(MONTH) to reset the MONTH to January. This 2974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is legacy behavior. Without this, clear(MONTH) has no effect, 2975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // since the internally set JULIAN_DAY is used. 2976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fStamp[UCAL_MILLISECONDS_IN_DAY] >= ((int32_t)kMinimumUserStamp) && 2977103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius newestStamp(UCAL_AM_PM, UCAL_MILLISECOND, kUnset) <= fStamp[UCAL_MILLISECONDS_IN_DAY]) { 2978103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius millisInDay = internalGet(UCAL_MILLISECONDS_IN_DAY); 2979103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 2980103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius millisInDay = computeMillisInDay(); 2981103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 2982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2983103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate t = 0; 2984103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (fStamp[UCAL_ZONE_OFFSET] >= ((int32_t)kMinimumUserStamp) || fStamp[UCAL_DST_OFFSET] >= ((int32_t)kMinimumUserStamp)) { 2985103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius t = millis + millisInDay - (internalGet(UCAL_ZONE_OFFSET) + internalGet(UCAL_DST_OFFSET)); 2986103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 2987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Compute the time zone offset and DST offset. There are two potential 2988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // ambiguities here. We'll assume a 2:00 am (wall time) switchover time 2989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // for discussion purposes here. 2990103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 2991103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 1. The positive offset change such as transition into DST. 2992103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Here, a designated time of 2:00 am - 2:59 am does not actually exist. 2993103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // For this case, skippedWallTime option specifies the behavior. 2994103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // For example, 2:30 am is interpreted as; 2995103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // - WALLTIME_LAST(default): 3:30 am (DST) (interpreting 2:30 am as 31 minutes after 1:59 am (STD)) 2996103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // - WALLTIME_FIRST: 1:30 am (STD) (interpreting 2:30 am as 30 minutes before 3:00 am (DST)) 2997103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // - WALLTIME_NEXT_VALID: 3:00 am (DST) (next valid time after 2:30 am on a wall clock) 2998103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 2. The negative offset change such as transition out of DST. 2999103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Here, a designated time of 1:00 am - 1:59 am can be in standard or DST. Both are valid 3000103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // representations (the rep jumps from 1:59:59 DST to 1:00:00 Std). 3001103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // For this case, repeatedWallTime option specifies the behavior. 3002103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // For example, 1:30 am is interpreted as; 3003103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // - WALLTIME_LAST(default): 1:30 am (STD) - latter occurrence 3004103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // - WALLTIME_FIRST: 1:30 am (DST) - former occurrence 3005103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 3006103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // In addition to above, when calendar is strict (not default), wall time falls into 3007103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the skipped time range will be processed as an error case. 3008103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 3009103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // These special cases are mostly handled in #computeZoneOffset(long), except WALLTIME_NEXT_VALID 3010103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // at positive offset change. The protected method computeZoneOffset(long) is exposed to Calendar 3011103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // subclass implementations and marked as @stable. Strictly speaking, WALLTIME_NEXT_VALID 3012103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // should be also handled in the same place, but we cannot change the code flow without deprecating 3013103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the protected method. 3014103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 3015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET 3016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // or DST_OFFSET fields; then we use those fields. 3017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3018103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!isLenient() || fSkippedWallTime == UCAL_WALLTIME_NEXT_VALID) { 3019103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // When strict, invalidate a wall time falls into a skipped wall time range. 3020103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // When lenient and skipped wall time option is WALLTIME_NEXT_VALID, 3021103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the result time will be adjusted to the next valid time (on wall clock). 3022103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t zoneOffset = computeZoneOffset(millis, millisInDay, status); 3023103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate tmpTime = millis + millisInDay - zoneOffset; 3024103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3025103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t raw, dst; 3026103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fZone->getOffset(tmpTime, FALSE, raw, dst, status); 3027103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3028103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_SUCCESS(status)) { 3029103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // zoneOffset != (raw + dst) only when the given wall time fall into 3030103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // a skipped wall time range caused by positive zone offset transition. 3031103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (zoneOffset != (raw + dst)) { 3032103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!isLenient()) { 3033103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius status = U_ILLEGAL_ARGUMENT_ERROR; 3034103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 3035103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(fSkippedWallTime == UCAL_WALLTIME_NEXT_VALID); 3036103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Adjust time to the next valid wall clock time. 3037103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // At this point, tmpTime is on or after the zone offset transition causing 3038103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the skipped time range. 3039fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate immediatePrevTransition; 3040fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool hasTransition = getImmediatePreviousZoneTransition(tmpTime, &immediatePrevTransition, status); 3041fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_SUCCESS(status) && hasTransition) { 3042fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius t = immediatePrevTransition; 3043103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3044103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3045103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 3046103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius t = tmpTime; 3047103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3048103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3049103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 3050103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius t = millis + millisInDay - computeZoneOffset(millis, millisInDay, status); 3051103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3052103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3053103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_SUCCESS(status)) { 3054103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius internalSetTime(t); 3055103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 3059fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Find the previous zone transtion near the given time. 3060fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 3061fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool Calendar::getImmediatePreviousZoneTransition(UDate base, UDate *transitionTime, UErrorCode& status) const { 3062fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius BasicTimeZone *btz = getBasicTimeZone(); 3063fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (btz) { 3064fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius TimeZoneTransition trans; 3065fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UBool hasTransition = btz->getPreviousTransition(base, TRUE, trans); 3066fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (hasTransition) { 3067fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *transitionTime = trans.getTime(); 3068fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 3069fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 3070fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Could not find any transitions. 3071fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Note: This should never happen. 3072fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_INTERNAL_PROGRAM_ERROR; 3073fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 3074fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 3075fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // If not BasicTimeZone, return unsupported error for now. 3076fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // TODO: We may support non-BasicTimeZone in future. 3077fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_UNSUPPORTED_ERROR; 3078fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 3079fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 3080fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 3081fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 3082fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/** 3083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Compute the milliseconds in the day from the fields. This is a 3084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* value from 0 to 23:59:59.999 inclusive, unless fields are out of 3085b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* range, in which case it can be an arbitrary value. This value 3086b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* reflects local zone wall time. 3087b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @stable ICU 2.0 3088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 3089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::computeMillisInDay() { 3090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do the time portion of the conversion. 3091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t millisInDay = 0; 3093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the best set of fields specifying the time of day. There 3095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // are only two possibilities here; the HOUR_OF_DAY or the 3096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // AM_PM and the HOUR. 3097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t hourOfDayStamp = fStamp[UCAL_HOUR_OF_DAY]; 3098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t hourStamp = (fStamp[UCAL_HOUR] > fStamp[UCAL_AM_PM])?fStamp[UCAL_HOUR]:fStamp[UCAL_AM_PM]; 3099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bestStamp = (hourStamp > hourOfDayStamp) ? hourStamp : hourOfDayStamp; 3100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Hours 3102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestStamp != kUnset) { 3103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestStamp == hourOfDayStamp) { 3104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Don't normalize here; let overflow bump into the next period. 3105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This is consistent with how we handle other fields. 3106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += internalGet(UCAL_HOUR_OF_DAY); 3107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Don't normalize here; let overflow bump into the next period. 3109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // This is consistent with how we handle other fields. 3110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += internalGet(UCAL_HOUR); 3111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += 12 * internalGet(UCAL_AM_PM); // Default works for unset AM_PM 3112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We use the fact that unset == 0; we start with millisInDay 3116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // == HOUR_OF_DAY. 3117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay *= 60; 3118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += internalGet(UCAL_MINUTE); // now have minutes 3119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay *= 60; 3120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += internalGet(UCAL_SECOND); // now have seconds 3121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay *= 1000; 3122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru millisInDay += internalGet(UCAL_MILLISECOND); // now have millis 3123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return millisInDay; 3125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 3128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* This method can assume EXTENDED_YEAR has been set. 3129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param millis milliseconds of the date fields 3130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @param millisInDay milliseconds of the time fields; may be out 3131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* or range. 3132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @stable ICU 2.0 3133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 3134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::computeZoneOffset(double millis, int32_t millisInDay, UErrorCode &ec) { 3135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t rawOffset, dstOffset; 3136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate wall = millis + millisInDay; 3137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius BasicTimeZone* btz = getBasicTimeZone(); 3138103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (btz) { 3139103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int duplicatedTimeOpt = (fRepeatedWallTime == UCAL_WALLTIME_FIRST) ? BasicTimeZone::kFormer : BasicTimeZone::kLatter; 3140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int nonExistingTimeOpt = (fSkippedWallTime == UCAL_WALLTIME_FIRST) ? BasicTimeZone::kLatter : BasicTimeZone::kFormer; 3141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius btz->getOffsetFromLocal(wall, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, ec); 3142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 3143103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const TimeZone& tz = getTimeZone(); 3144103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // By default, TimeZone::getOffset behaves UCAL_WALLTIME_LAST for both. 3145103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tz.getOffset(wall, TRUE, rawOffset, dstOffset, ec); 3146103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3147103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool sawRecentNegativeShift = FALSE; 3148103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (fRepeatedWallTime == UCAL_WALLTIME_FIRST) { 3149103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Check if the given wall time falls into repeated time range 3150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate tgmt = wall - (rawOffset + dstOffset); 3151103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3152103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Any negative zone transition within last 6 hours? 3153103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Note: The maximum historic negative zone transition is -3 hours in the tz database. 3154103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // 6 hour window would be sufficient for this purpose. 3155103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t tmpRaw, tmpDst; 3156103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tz.getOffset(tgmt - 6*60*60*1000, FALSE, tmpRaw, tmpDst, ec); 3157103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t offsetDelta = (rawOffset + dstOffset) - (tmpRaw + tmpDst); 3158103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3159103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(offsetDelta < -6*60*60*1000); 3160103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (offsetDelta < 0) { 3161103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius sawRecentNegativeShift = TRUE; 3162103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Negative shift within last 6 hours. When UCAL_WALLTIME_FIRST is used and the given wall time falls 3163103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // into the repeated time range, use offsets before the transition. 3164103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Note: If it does not fall into the repeated time range, offsets remain unchanged below. 3165103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tz.getOffset(wall + offsetDelta, TRUE, rawOffset, dstOffset, ec); 3166103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!sawRecentNegativeShift && fSkippedWallTime == UCAL_WALLTIME_FIRST) { 3169103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // When skipped wall time option is WALLTIME_FIRST, 3170103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // recalculate offsets from the resolved time (non-wall). 3171103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // When the given wall time falls into skipped wall time, 3172103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the offsets will be based on the zone offsets AFTER 3173103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // the transition (which means, earliest possibe interpretation). 3174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate tgmt = wall - (rawOffset + dstOffset); 3175103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tz.getOffset(tgmt, FALSE, rawOffset, dstOffset, ec); 3176103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return rawOffset + dstOffset; 3179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::computeJulianDay() 3182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We want to see if any of the date fields is newer than the 3184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // JULIAN_DAY. If not, then we use JULIAN_DAY. If so, then we do 3185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the normal resolution. We only use JULIAN_DAY if it has been 3186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // set by the user. This makes it possible for the caller to set 3187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the calendar to a time and call clear(MONTH) to reset the MONTH 3188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // to January. This is legacy behavior. Without this, 3189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // clear(MONTH) has no effect, since the internally set JULIAN_DAY 3190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // is used. 3191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (fStamp[UCAL_JULIAN_DAY] >= (int32_t)kMinimumUserStamp) { 3192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t bestStamp = newestStamp(UCAL_ERA, UCAL_DAY_OF_WEEK_IN_MONTH, kUnset); 3193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bestStamp = newestStamp(UCAL_YEAR_WOY, UCAL_EXTENDED_YEAR, bestStamp); 3194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestStamp <= fStamp[UCAL_JULIAN_DAY]) { 3195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return internalGet(UCAL_JULIAN_DAY); 3196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UCalendarDateFields bestField = resolveFields(getFieldResolutionTable()); 3200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestField == UCAL_FIELD_COUNT) { 3201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bestField = UCAL_DAY_OF_MONTH; 3202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return handleComputeJulianDay(bestField); 3205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------------- 3208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) { 3210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool useMonth = (bestField == UCAL_DAY_OF_MONTH || 3211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bestField == UCAL_WEEK_OF_MONTH || 3212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bestField == UCAL_DAY_OF_WEEK_IN_MONTH); 3213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year; 3214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestField == UCAL_WEEK_OF_YEAR) { 3216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = internalGet(UCAL_YEAR_WOY, handleGetExtendedYear()); 3217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_EXTENDED_YEAR, year); 3218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = handleGetExtendedYear(); 3220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet(UCAL_EXTENDED_YEAR, year); 3221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d: bestField= %s - y=%d\n", __FILE__, __LINE__, fldName(bestField), year); 3225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the Julian day of the day BEFORE the start of this year. 3228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If useMonth is true, get the day before the start of the month. 3229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // give calendar subclass a chance to have a default 'first' month 3231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t month; 3232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(isSet(UCAL_MONTH)) { 3234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = internalGet(UCAL_MONTH); 3235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3236b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru month = getDefaultMonthInYear(year); 3237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t julianDay = handleComputeMonthStart(year, useMonth ? month : 0, useMonth); 3240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestField == UCAL_DAY_OF_MONTH) { 3242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // give calendar subclass a chance to have a default 'first' dom 3244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dayOfMonth; 3245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(isSet(UCAL_DAY_OF_MONTH)) { 3246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dayOfMonth = internalGet(UCAL_DAY_OF_MONTH,1); 3247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3248b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru dayOfMonth = getDefaultDayInMonth(year, month); 3249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return julianDay + dayOfMonth; 3251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestField == UCAL_DAY_OF_YEAR) { 3254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return julianDay + internalGet(UCAL_DAY_OF_YEAR); 3255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t firstDayOfWeek = getFirstDayOfWeek(); // Localized fdw 3258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // At this point julianDay is the 0-based day BEFORE the first day of 3260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // January 1, year 1 of the given calendar. If julianDay == 0, it 3261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian 3262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // or Gregorian). (or it is before the month we are in, if useMonth is True) 3263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // At this point we need to process the WEEK_OF_MONTH or 3265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH. 3266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First, perform initial shared computations. These locate the 3267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first week of the period. 3268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the 0-based localized DOW of day one of the month or year. 3270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Valid range 0..6. 3271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t first = julianDayToDayOfWeek(julianDay + 1) - firstDayOfWeek; 3272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (first < 0) { 3273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first += 7; 3274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dowLocal = getLocalDOW(); 3277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Find the first target DOW (dowLocal) in the month or year. 3279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Actually, it may be just before the first of the month or year. 3280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It will be an integer from -5..7. 3281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t date = 1 - first + dowLocal; 3282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bestField == UCAL_DAY_OF_WEEK_IN_MONTH) { 3284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Adjust the target DOW to be in the month or year. 3285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (date < 1) { 3286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date += 7; 3287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // The only trickiness occurs if the day-of-week-in-month is 3290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // negative. 3291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dim = internalGet(UCAL_DAY_OF_WEEK_IN_MONTH, 1); 3292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dim >= 0) { 3293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date += 7*(dim - 1); 3294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Move date to the last of this day-of-week in this month, 3297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // then back up as needed. If dim==-1, we don't back up at 3298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // all. If dim==-2, we back up once, etc. Don't back up 3299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // past the first of the given day-of-week in this month. 3300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Note that we handle -2, -3, etc. correctly, even though 3301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // values < -1 are technically disallowed. 3302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t m = internalGet(UCAL_MONTH, UCAL_JANUARY); 3303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t monthLength = handleGetMonthLength(year, m); 3304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date += ((monthLength - date) / 7 + dim + 1) * 7; 3305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d - bf= %s\n", __FILE__, __LINE__, fldName(bestField)); 3309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(bestField == UCAL_WEEK_OF_YEAR) { // ------------------------------------- WOY ------------- 3312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!isSet(UCAL_YEAR_WOY) || // YWOY not set at all or 3313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ( (resolveFields(kYearPrecedence) != UCAL_YEAR_WOY) // YWOY doesn't have precedence 3314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru && (fStamp[UCAL_YEAR_WOY]!=kInternallySet) ) ) // (excluding where all fields are internally set - then YWOY is used) 3315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 3316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // need to be sure to stay in 'real' year. 3317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t woy = internalGet(bestField); 3318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t nextJulianDay = handleComputeMonthStart(year+1, 0, FALSE); // jd of day before jan 1 3320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek; 3321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (nextFirst < 0) { // 0..6 ldow of Jan 1 3323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextFirst += 7; 3324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(woy==1) { // FIRST WEEK --------------------------------- 3327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d - woy=%d, yp=%d, nj(%d)=%d, nf=%d", __FILE__, __LINE__, 3329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalGet(bestField), resolveFields(kYearPrecedence), year+1, 3330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru nextJulianDay, nextFirst); 3331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, " next: %d DFW, min=%d \n", (7-nextFirst), getMinimalDaysInFirstWeek() ); 3333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // nextFirst is now the localized DOW of Jan 1 of y-woy+1 3336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if((nextFirst > 0) && // Jan 1 starts on FDOW 3337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (7-nextFirst) >= getMinimalDaysInFirstWeek()) // or enough days in the week 3338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 3339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Jan 1 of (yearWoy+1) is in yearWoy+1 - recalculate JD to next year 3340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d - was going to move JD from %d to %d [d%d]\n", __FILE__, __LINE__, 3342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru julianDay, nextJulianDay, (nextJulianDay-julianDay)); 3343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru julianDay = nextJulianDay; 3345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // recalculate 'first' [0-based local dow of jan 1] 3347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first = julianDayToDayOfWeek(julianDay + 1) - firstDayOfWeek; 3348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (first < 0) { 3349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first += 7; 3350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // recalculate date. 3352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date = 1 - first + dowLocal; 3353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(woy>=getLeastMaximum(bestField)) { 3355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // could be in the last week- find out if this JD would overstep 3356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t testDate = date; 3357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - first) < getMinimalDaysInFirstWeek()) { 3358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru testDate += 7; 3359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now adjust for the week number. 3362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru testDate += 7 * (woy - 1); 3363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d - y=%d, y-1=%d doy%d, njd%d (C.F. %d)\n", 3366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__, year, year-1, testDate, julianDay+testDate, nextJulianDay); 3367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(julianDay+testDate > nextJulianDay) { // is it past Dec 31? (nextJulianDay is day BEFORE year+1's Jan 1) 3369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Fire up the calculating engines.. retry YWOY = (year-1) 3370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru julianDay = handleComputeMonthStart(year-1, 0, FALSE); // jd before Jan 1 of previous year 3371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first = julianDayToDayOfWeek(julianDay + 1) - firstDayOfWeek; // 0 based local dow of first week 3372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(first < 0) { // 0..6 3374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first += 7; 3375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date = 1 - first + dowLocal; 3377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "%s:%d - date now %d, jd%d, ywoy%d\n", 3380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru __FILE__, __LINE__, date, julianDay, year-1); 3381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } /* correction needed */ 3385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } /* leastmaximum */ 3386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } /* resolvefields(year) != year_woy */ 3387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } /* bestfield != week_of_year */ 3388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // assert(bestField == WEEK_OF_MONTH || bestField == WEEK_OF_YEAR) 3390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Adjust for minimal days in first week 3391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if ((7 - first) < getMinimalDaysInFirstWeek()) { 3392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date += 7; 3393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now adjust for the week number. 3396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru date += 7 * (internalGet(bestField) - 1); 3397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return julianDay + date; 3400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 3403b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCalendar::getDefaultMonthInYear(int32_t /*eyear*/) 3404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 3406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 3409b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCalendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/) 3410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 1; 3412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::getLocalDOW() 3416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get zero-based localized DOW, valid range 0..6. This is the DOW 3418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we are looking for. 3419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dowLocal = 0; 3420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (resolveFields(kDOWPrecedence)) { 3421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK: 3422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal = internalGet(UCAL_DAY_OF_WEEK) - fFirstDayOfWeek; 3423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DOW_LOCAL: 3425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal = internalGet(UCAL_DOW_LOCAL) - 1; 3426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 3428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal = dowLocal % 7; 3431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dowLocal < 0) { 3432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal += 7; 3433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return dowLocal; 3435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy) 3438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine 3440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // what year we fall in, so that other code can set it properly. 3441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // (code borrowed from computeWeekFields and handleComputeJulianDay) 3442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //return yearWoy; 3443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First, we need a reliable DOW. 3445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields 3446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Now, a local DOW 3448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dowLocal = getLocalDOW(); // 0..6 3449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t firstDayOfWeek = getFirstDayOfWeek(); // Localized fdw 3450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t jan1Start = handleComputeMonthStart(yearWoy, 0, FALSE); 3451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t nextJan1Start = handleComputeMonthStart(yearWoy+1, 0, FALSE); // next year's Jan1 start 3452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // At this point julianDay is the 0-based day BEFORE the first day of 3454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // January 1, year 1 of the given calendar. If julianDay == 0, it 3455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian 3456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // or Gregorian). (or it is before the month we are in, if useMonth is True) 3457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // At this point we need to process the WEEK_OF_MONTH or 3459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH. 3460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First, perform initial shared computations. These locate the 3461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first week of the period. 3462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Get the 0-based localized DOW of day one of the month or year. 3464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Valid range 0..6. 3465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t first = julianDayToDayOfWeek(jan1Start + 1) - firstDayOfWeek; 3466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (first < 0) { 3467b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru first += 7; 3468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3469f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 3470f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius //// (nextFirst was not used below) 3471f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // int32_t nextFirst = julianDayToDayOfWeek(nextJan1Start + 1) - firstDayOfWeek; 3472f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // if (nextFirst < 0) { 3473f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius // nextFirst += 7; 3474f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius //} 3475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t minDays = getMinimalDaysInFirstWeek(); 3477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UBool jan1InPrevYear = FALSE; // January 1st in the year of WOY is the 1st week? (i.e. first week is < minimal ) 3478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week? 3479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if((7 - first) < minDays) { 3481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru jan1InPrevYear = TRUE; 3482b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if((7 - nextFirst) < minDays) { 3485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // nextJan1InPrevYear = TRUE; 3486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // } 3487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch(bestField) { 3489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_YEAR: 3490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(woy == 1) { 3491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(jan1InPrevYear == TRUE) { 3492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the first week of January is in the previous year 3493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // therefore WOY1 is always solidly within yearWoy 3494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // First WOY is split between two years 3497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if( dowLocal < first) { // we are prior to Jan 1 3498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy-1; // previous year 3499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; // in this year 3501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(woy >= getLeastMaximum(bestField)) { 3504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we _might_ be in the last week.. 3505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t jd = // Calculate JD of our target day: 3506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru jan1Start + // JD of Jan 1 3507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (7-first) + // days in the first week (Jan 1.. ) 3508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (woy-1)*7 + // add the weeks of the year 3509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dowLocal; // the local dow (0..6) of last week 3510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(jan1InPrevYear==FALSE) { 3511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru jd -= 7; // woy already includes Jan 1's week. 3512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if( (jd+1) >= nextJan1Start ) { 3515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we are in week 52 or 53 etc. - actual year is yearWoy+1 3516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy+1; 3517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // still in yearWoy; 3519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we're not possibly in the last week -must be ywoy 3523b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DATE: 3527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if((internalGet(UCAL_MONTH)==0) && 3528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (woy >= getLeastMaximum(UCAL_WEEK_OF_YEAR))) { 3529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy+1; // month 0, late woy = in the next year 3530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else if(woy==1) { 3531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //if(nextJan1InPrevYear) { 3532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(internalGet(UCAL_MONTH)==0) { 3533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 3535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy-1; 3536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //} 3538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //(internalGet(UCAL_DATE) <= (7-first)) /* && in minDow */ ) { 3541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //within 1st week and in this month.. 3542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru //return yearWoy+1; 3543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: // assume the year is appropriate 3546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return yearWoy; 3547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const 3551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return handleComputeMonthStart(extendedYear, month+1, TRUE) - 3553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru handleComputeMonthStart(extendedYear, month, TRUE); 3554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::handleGetYearLength(int32_t eyear) const { 3557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return handleComputeMonthStart(eyear+1, 0, FALSE) - 3558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru handleComputeMonthStart(eyear, 0, FALSE); 3559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 3562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode& status) const 3563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t result; 3565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 3566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DATE: 3567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 3568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) return 0; 3569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar *cal = clone(); 3570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!cal) { status = U_MEMORY_ALLOCATION_ERROR; return 0; } 3571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cal->setLenient(TRUE); 3572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cal->prepareGetActual(field,FALSE,status); 3573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = handleGetMonthLength(cal->get(UCAL_EXTENDED_YEAR, status), cal->get(UCAL_MONTH, status)); 3574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete cal; 3575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_YEAR: 3579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 3580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) return 0; 3581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar *cal = clone(); 3582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!cal) { status = U_MEMORY_ALLOCATION_ERROR; return 0; } 3583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cal->setLenient(TRUE); 3584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru cal->prepareGetActual(field,FALSE,status); 3585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = handleGetYearLength(cal->get(UCAL_EXTENDED_YEAR, status)); 3586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete cal; 3587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK: 3591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_AM_PM: 3592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR: 3593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_HOUR_OF_DAY: 3594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MINUTE: 3595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_SECOND: 3596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECOND: 3597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_ZONE_OFFSET: 3598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DST_OFFSET: 3599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DOW_LOCAL: 3600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_JULIAN_DAY: 3601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MILLISECONDS_IN_DAY: 3602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // These fields all have fixed minima/maxima 3603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = getMaximum(field); 3604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 3607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For all other fields, do it the hard way.... 3608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru result = getActualHelper(field, getLeastMaximum(field), getMaximum(field),status); 3609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 3612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 3616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Prepare this calendar for computing the actual minimum or maximum. 3617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* This method modifies this calendar's fields; it is called on a 3618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* temporary calendar. 3619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 3620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p>Rationale: The semantics of getActualXxx() is to return the 3621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* maximum or minimum value that the given field can take, taking into 3622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* account other relevant fields. In general these other fields are 3623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* larger fields. For example, when computing the actual maximum 3624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* DATE, the current value of DATE itself is ignored, 3625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* as is the value of any field smaller. 3626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 3627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p>The time fields all have fixed minima and maxima, so we don't 3628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* need to worry about them. This also lets us set the 3629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* MILLISECONDS_IN_DAY to zero to erase any effects the time fields 3630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* might have when computing date fields. 3631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 3632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* <p>DAY_OF_WEEK is adjusted specially for the WEEK_OF_MONTH and 3633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* WEEK_OF_YEAR fields to ensure that they are computed correctly. 3634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @internal 3635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 3636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErrorCode &status) 3637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_MILLISECONDS_IN_DAY, 0); 3639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch (field) { 3641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_YEAR: 3642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_EXTENDED_YEAR: 3643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DAY_OF_YEAR, getGreatestMinimum(UCAL_DAY_OF_YEAR)); 3644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3646c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru case UCAL_YEAR_WOY: 3647c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru set(UCAL_WEEK_OF_YEAR, getGreatestMinimum(UCAL_WEEK_OF_YEAR)); 3648c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 3649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_MONTH: 3650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DATE, getGreatestMinimum(UCAL_DATE)); 3651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_DAY_OF_WEEK_IN_MONTH: 3654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // For dowim, the maximum occurs for the DOW of the first of the 3655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // month. 3656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DATE, 1); 3657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DAY_OF_WEEK, get(UCAL_DAY_OF_WEEK, status)); // Make this user set 3658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_MONTH: 3661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case UCAL_WEEK_OF_YEAR: 3662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If we're counting weeks, set the day of the week to either the 3663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first or last localized DOW. We know the last week of a month 3664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // or year will contain the first day of the week, and that the 3665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // first week will contain the last DOW. 3666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 3667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t dow = fFirstDayOfWeek; 3668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isMinimum) { 3669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dow = (dow + 6) % 7; // set to last DOW 3670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dow < UCAL_SUNDAY) { 3671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru dow += 7; 3672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "prepareGetActualHelper(WOM/WOY) - dow=%d\n", dow); 3676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(UCAL_DAY_OF_WEEK, dow); 3678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 3680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 3681c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru break; 3682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // Do this last to give it the newest time stamp 3685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru set(field, getGreatestMinimum(field)); 3686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue, int32_t endValue, UErrorCode &status) const 3689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "getActualHelper(%d,%d .. %d, %s)\n", field, startValue, endValue, u_errorName(status)); 3692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (startValue == endValue) { 3694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // if we know that the maximum value is always the same, just return it 3695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return startValue; 3696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 3697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t delta = (endValue > startValue) ? 1 : -1; 3699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // clone the calendar so we don't mess with the real one, and set it to 3701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // accept anything for the field values 3702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) return startValue; 3703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru Calendar *work = clone(); 3704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(!work) { status = U_MEMORY_ALLOCATION_ERROR; return startValue; } 3705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // need to resolve time here, otherwise, fields set for actual limit 3707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // may cause conflict with fields previously set (but not yet resolved). 3708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho work->complete(status); 3709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru work->setLenient(TRUE); 3711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru work->prepareGetActual(field, delta < 0, status); 3712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // now try each value from the start to the end one by one until 3714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // we get a value that normalizes to another value. The last value that 3715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // normalizes to itself is the actual maximum for the current date 3716c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru work->set(field, startValue); 3717c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 3718c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru // prepareGetActual sets the first day of week in the same week with 3719c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru // the first day of a month. Unlike WEEK_OF_YEAR, week number for the 3720c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru // week which contains days from both previous and current month is 3721c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru // not unique. For example, last several days in the previous month 3722c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru // is week 5, and the rest of week is week 1. 3723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t result = startValue; 372427f654740f2a26ad62a5c155af9199af9e69b889claireho if ((work->get(field, status) != startValue 372527f654740f2a26ad62a5c155af9199af9e69b889claireho && field != UCAL_WEEK_OF_MONTH && delta > 0 ) || U_FAILURE(status)) { 3726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3727c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru fprintf(stderr, "getActualHelper(fld %d) - got %d (not %d) - %s\n", field, work->get(field,status), startValue, u_errorName(status)); 3728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3729c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else { 3730c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru do { 3731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru startValue += delta; 3732c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru work->add(field, delta, status); 3733c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (work->get(field, status) != startValue || U_FAILURE(status)) { 3734c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3735c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru fprintf(stderr, "getActualHelper(fld %d) - got %d (not %d), BREAK - %s\n", field, work->get(field,status), startValue, u_errorName(status)); 3736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3737c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru break; 3738c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 3739c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru result = startValue; 3740c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } while (startValue != endValue); 3741c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 3742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete work; 3743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CAL) 3744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "getActualHelper(%d) = %d\n", field, result); 3745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 3747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ------------------------------------- 3753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 375550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& status) 3756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) return; 3759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fFirstDayOfWeek = UCAL_SUNDAY; 3761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fMinimalDaysInFirstWeek = 1; 376250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnset = UCAL_SATURDAY; 376350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendOnsetMillis = 0; 376450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCease = UCAL_SUNDAY; 376550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho fWeekendCeaseMillis = 86400000; // 24*60*60*1000 3766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 376727f654740f2a26ad62a5c155af9199af9e69b889claireho // Since week and weekend data is territory based instead of language based, 376827f654740f2a26ad62a5c155af9199af9e69b889claireho // we may need to tweak the locale that we are using to try to get the appropriate 376927f654740f2a26ad62a5c155af9199af9e69b889claireho // values, using the following logic: 377027f654740f2a26ad62a5c155af9199af9e69b889claireho // 1). If the locale has a language but no territory, use the territory as defined by 377127f654740f2a26ad62a5c155af9199af9e69b889claireho // the likely subtags. 377227f654740f2a26ad62a5c155af9199af9e69b889claireho // 2). If the locale has a script designation then we ignore it, 377327f654740f2a26ad62a5c155af9199af9e69b889claireho // then remove it ( i.e. "en_Latn_US" becomes "en_US" ) 377427f654740f2a26ad62a5c155af9199af9e69b889claireho 377527f654740f2a26ad62a5c155af9199af9e69b889claireho char minLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 }; 377627f654740f2a26ad62a5c155af9199af9e69b889claireho UErrorCode myStatus = U_ZERO_ERROR; 377727f654740f2a26ad62a5c155af9199af9e69b889claireho 377827f654740f2a26ad62a5c155af9199af9e69b889claireho uloc_minimizeSubtags(desiredLocale.getName(),minLocaleID,ULOC_FULLNAME_CAPACITY,&myStatus); 377927f654740f2a26ad62a5c155af9199af9e69b889claireho Locale min = Locale::createFromName(minLocaleID); 378027f654740f2a26ad62a5c155af9199af9e69b889claireho Locale useLocale; 378127f654740f2a26ad62a5c155af9199af9e69b889claireho if ( uprv_strlen(desiredLocale.getCountry()) == 0 || 3782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho (uprv_strlen(desiredLocale.getScript()) > 0 && uprv_strlen(min.getScript()) == 0) ) { 378327f654740f2a26ad62a5c155af9199af9e69b889claireho char maxLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 }; 378427f654740f2a26ad62a5c155af9199af9e69b889claireho myStatus = U_ZERO_ERROR; 378527f654740f2a26ad62a5c155af9199af9e69b889claireho uloc_addLikelySubtags(desiredLocale.getName(),maxLocaleID,ULOC_FULLNAME_CAPACITY,&myStatus); 378627f654740f2a26ad62a5c155af9199af9e69b889claireho Locale max = Locale::createFromName(maxLocaleID); 378727f654740f2a26ad62a5c155af9199af9e69b889claireho useLocale = Locale(max.getLanguage(),max.getCountry()); 378827f654740f2a26ad62a5c155af9199af9e69b889claireho } else { 378927f654740f2a26ad62a5c155af9199af9e69b889claireho useLocale = Locale(desiredLocale); 379027f654740f2a26ad62a5c155af9199af9e69b889claireho } 379127f654740f2a26ad62a5c155af9199af9e69b889claireho 3792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho /* The code here is somewhat of a hack, since week data and weekend data aren't really tied to 3793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho a specific calendar, they aren't truly locale data. But this is the only place where valid and 3794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho actual locale can be set, so we take a shot at it here by loading a representative resource 3795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho from the calendar data. The code used to use the dateTimeElements resource to get first day 3796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho of week data, but this was moved to supplemental data under ticket 7755. (JCE) */ 3797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho CalendarData calData(useLocale,type,status); 3799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *monthNames = calData.getByKey(gMonthNames,status); 3800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 3801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_LOCALE_BASED(locBased,*this); 3802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho locBased.setLocaleIDs(ures_getLocaleByType(monthNames, ULOC_VALID_LOCALE, &status), 3803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getLocaleByType(monthNames, ULOC_ACTUAL_LOCALE, &status)); 3804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 3805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_USING_FALLBACK_WARNING; 3806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 3807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Read week data values from supplementalData week data 3811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status); 3812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getByKey(rb, "weekData", rb, &status); 3813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *weekData = ures_getByKey(rb, useLocale.getCountry(), NULL, &status); 3814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (status == U_MISSING_RESOURCE_ERROR && rb != NULL) { 3815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_ZERO_ERROR; 3816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho weekData = ures_getByKey(rb, "001", NULL, &status); 3817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 381950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 3820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined (U_DEBUG_CALDATA) 3821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fprintf(stderr, " Failure loading weekData from supplemental = %s\n", u_errorName(status)); 3822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif 3823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_USING_FALLBACK_WARNING; 382450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 3825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t arrLen; 3826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const int32_t *weekDataArr = ures_getIntVector(weekData,&arrLen,&status); 3827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if( U_SUCCESS(status) && arrLen == 6 3828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && 1 <= weekDataArr[0] && weekDataArr[0] <= 7 3829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && 1 <= weekDataArr[1] && weekDataArr[1] <= 7 3830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && 1 <= weekDataArr[2] && weekDataArr[2] <= 7 3831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && 1 <= weekDataArr[4] && weekDataArr[4] <= 7) { 3832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fFirstDayOfWeek = (UCalendarDaysOfWeek)weekDataArr[0]; 3833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fMinimalDaysInFirstWeek = (uint8_t)weekDataArr[1]; 3834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fWeekendOnset = (UCalendarDaysOfWeek)weekDataArr[2]; 3835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fWeekendOnsetMillis = weekDataArr[3]; 3836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fWeekendCease = (UCalendarDaysOfWeek)weekDataArr[4]; 3837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fWeekendCeaseMillis = weekDataArr[5]; 383850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 3839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_INVALID_FORMAT_ERROR; 384050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 384150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 3842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(weekData); 3843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(rb); 3844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 3847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Recompute the time and update the status fields isTimeSet 3848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* and areFieldsSet. Callers should check isTimeSet and only 3849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* call this method if isTimeSet is false. 3850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 3851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 3852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::updateTime(UErrorCode& status) 3853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru computeTime(status); 3855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(status)) 3856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 3857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // If we are lenient, we need to recompute the fields to normalize 3859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // the values. Also, if we haven't set all the fields yet (i.e., 3860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // in a newly-created object), we need to fill in the fields. [LIU] 3861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (isLenient() || ! fAreAllFieldsSet) 3862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsSet = FALSE; 3863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fIsTimeSet = TRUE; 3865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fAreFieldsVirtuallySet = FALSE; 3866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruLocale 3869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getLocale(ULocDataLocaleType type, UErrorCode& status) const { 3870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_LOCALE_BASED(locBased, *this); 3871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return locBased.getLocale(type, status); 3872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst char * 3875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::getLocaleID(ULocDataLocaleType type, UErrorCode& status) const { 3876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_LOCALE_BASED(locBased, *this); 3877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return locBased.getLocaleID(type, status); 3878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid 3881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCalendar::recalculateStamp() { 3882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t index; 3883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t currentValue; 3884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t j, i; 3885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fNextStamp = 1; 3887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (j = 0; j < UCAL_FIELD_COUNT; j++) { 3889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho currentValue = STAMP_MAX; 3890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho index = -1; 3891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (i = 0; i < UCAL_FIELD_COUNT; i++) { 3892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fStamp[i] > fNextStamp && fStamp[i] < currentValue) { 3893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho currentValue = fStamp[i]; 3894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho index = i; 3895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (index >= 0) { 3899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fStamp[index] = ++fNextStamp; 3900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 3901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 3902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 3904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fNextStamp++; 3905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 3906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Deprecated function. This doesn't need to be inline. 3908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid 3909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendar::internalSet(EDateFields field, int32_t value) 3910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 3911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru internalSet((UCalendarDateFields) field, value); 3912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 3913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3914103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusBasicTimeZone* 3915103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendar::getBasicTimeZone(void) const { 3916103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (dynamic_cast<const OlsonTimeZone *>(fZone) != NULL 3917103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius || dynamic_cast<const SimpleTimeZone *>(fZone) != NULL 3918103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius || dynamic_cast<const RuleBasedTimeZone *>(fZone) != NULL 3919103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius || dynamic_cast<const VTimeZone *>(fZone) != NULL) { 3920103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return (BasicTimeZone*)fZone; 3921103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 3922103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 3923103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 3924103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 3925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 3926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 3928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 3930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof 393159d709d503bab6e2b61931737e662dd293b40578ccornelius 3932