1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
359d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 2005-2013, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File WINDTFMT.CPP
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#if U_PLATFORM_HAS_WIN32_API
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/format.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/fmtable.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/datefmt.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/msgfmt.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/calendar.h"
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/gregocal.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/locid.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unistr.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/timezone.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utmscale.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uresimp.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "windtfmt.h"
3485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "wintzimpl.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define WIN32_LEAN_AND_MEAN
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define VC_EXTRALEAN
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOUSER
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOSERVICE
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOIME
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOMCX
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <windows.h>
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32DateFormat)
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DELETE_ARRAY(array) uprv_free((void *) (array))
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define STACK_BUFFER_SIZE 64
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
5585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUnicodeString* Win32DateFormat::getTimeDateFormat(const Calendar *cal, const Locale *locale, UErrorCode &status) const
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString *result = NULL;
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *type = cal->getType();
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char *base = locale->getBaseName();
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *topBundle = ures_open((char *) 0, base, &status);
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *calBundle = ures_getByKey(topBundle, "calendar", NULL, &status);
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *typBundle = ures_getByKeyWithFallback(calBundle, type, NULL, &status);
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle *patBundle = ures_getByKeyWithFallback(typBundle, "DateTimePatterns", NULL, &status);
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (status == U_MISSING_RESOURCE_ERROR) {
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR;
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        typBundle = ures_getByKeyWithFallback(calBundle, "gregorian", typBundle, &status);
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        patBundle = ures_getByKeyWithFallback(typBundle, "DateTimePatterns", patBundle, &status);
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        static const UChar defaultPattern[] = {0x007B, 0x0031, 0x007D, 0x0020, 0x007B, 0x0030, 0x007D, 0x0000}; // "{1} {0}"
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return new UnicodeString(defaultPattern, ARRAY_SIZE(defaultPattern));
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t resStrLen = 0;
7785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t glueIndex = DateFormat::kDateTime;
7885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t patSize = ures_getSize(patBundle);
7985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (patSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
8085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // Get proper date time format
8185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        glueIndex = (int32_t)(DateFormat::kDateTimeOffset + (fDateStyle - DateFormat::kDateOffset));
8285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
8385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UChar *resStr = ures_getStringByIndex(patBundle, glueIndex, &resStrLen, &status);
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = new UnicodeString(TRUE, resStr, resStrLen);
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(patBundle);
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(typBundle);
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(calBundle);
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(topBundle);
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// TODO: Range-check timeStyle, dateStyle
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32DateFormat::Win32DateFormat(DateFormat::EStyle timeStyle, DateFormat::EStyle dateStyle, const Locale &locale, UErrorCode &status)
9759d709d503bab6e2b61931737e662dd293b40578ccornelius  : DateFormat(), fDateTimeMsg(NULL), fTimeStyle(timeStyle), fDateStyle(dateStyle), fLocale(locale), fZoneID()
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fLCID = locale.getLCID();
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fTZI = NEW_ARRAY(TIME_ZONE_INFORMATION, 1);
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memset(fTZI, 0, sizeof(TIME_ZONE_INFORMATION));
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        adoptCalendar(Calendar::createInstance(locale, status));
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32DateFormat::Win32DateFormat(const Win32DateFormat &other)
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : DateFormat(other)
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *this = other;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32DateFormat::~Win32DateFormat()
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    delete fCalendar;
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(fTZI);
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fDateTimeMsg;
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32DateFormat &Win32DateFormat::operator=(const Win32DateFormat &other)
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The following handles fCalendar
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    DateFormat::operator=(other);
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    delete fCalendar;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fDateTimeMsg = other.fDateTimeMsg;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fTimeStyle   = other.fTimeStyle;
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fDateStyle   = other.fDateStyle;
13059d709d503bab6e2b61931737e662dd293b40578ccornelius    this->fLocale      = other.fLocale;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fLCID        = other.fLCID;
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    this->fCalendar    = other.fCalendar->clone();
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fZoneID      = other.fZoneID;
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fTZI = NEW_ARRAY(TIME_ZONE_INFORMATION, 1);
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *this->fTZI = *other.fTZI;
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat *Win32DateFormat::clone(void) const
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return new Win32DateFormat(*this);
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// TODO: Is just ignoring pos the right thing?
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString &Win32DateFormat::format(Calendar &cal, UnicodeString &appendTo, FieldPosition &pos) const
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FILETIME ft;
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SYSTEMTIME st_gmt;
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SYSTEMTIME st_local;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TIME_ZONE_INFORMATION tzi = *fTZI;
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const TimeZone &tz = cal.getTimeZone();
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int64_t uct, uft;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setTimeZoneInfo(&tzi, tz);
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uct = utmscale_fromInt64((int64_t) cal.getTime(status), UDTS_ICU4C_TIME, &status);
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uft = utmscale_toInt64(uct, UDTS_WINDOWS_FILE_TIME, &status);
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ft.dwLowDateTime =  (DWORD) (uft & 0xFFFFFFFF);
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ft.dwHighDateTime = (DWORD) ((uft >> 32) & 0xFFFFFFFF);
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FileTimeToSystemTime(&ft, &st_gmt);
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SystemTimeToTzSpecificLocalTime(&tzi, &st_gmt, &st_local);
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) {
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString *date = new UnicodeString();
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString *time = new UnicodeString();
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString *pattern = fDateTimeMsg;
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Formattable timeDateArray[2];
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatDate(&st_local, *date);
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatTime(&st_local, *time);
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        timeDateArray[0].adoptString(time);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        timeDateArray[1].adoptString(date);
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (strcmp(fCalendar->getType(), cal.getType()) != 0) {
18259d709d503bab6e2b61931737e662dd293b40578ccornelius            pattern = getTimeDateFormat(&cal, &fLocale, status);
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        MessageFormat::format(*pattern, timeDateArray, 2, appendTo, status);
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (fDateStyle != DateFormat::kNone) {
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatDate(&st_local, appendTo);
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (fTimeStyle != DateFormat::kNone) {
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatTime(&st_local, appendTo);
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& pos) const
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setErrorIndex(pos.getIndex());
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::adoptCalendar(Calendar *newCalendar)
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fCalendar == NULL || strcmp(fCalendar->getType(), newCalendar->getType()) != 0) {
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete fDateTimeMsg;
20759d709d503bab6e2b61931737e662dd293b40578ccornelius            fDateTimeMsg = getTimeDateFormat(newCalendar, &fLocale, status);
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fCalendar;
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar = newCalendar;
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, fCalendar->getTimeZone());
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::setCalendar(const Calendar &newCalendar)
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    adoptCalendar(newCalendar.clone());
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::adoptTimeZone(TimeZone *zoneToAdopt)
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, *zoneToAdopt);
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->adoptTimeZone(zoneToAdopt);
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::setTimeZone(const TimeZone& zone)
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, zone);
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->setTimeZone(zone);
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const DWORD dfFlags[] = {DATE_LONGDATE, DATE_LONGDATE, DATE_SHORTDATE, DATE_SHORTDATE};
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::formatDate(const SYSTEMTIME *st, UnicodeString &appendTo) const
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar stackBuffer[STACK_BUFFER_SIZE];
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *buffer = stackBuffer;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, STACK_BUFFER_SIZE);
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result == 0) {
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int newLength = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, NULL, 0);
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buffer = NEW_ARRAY(UChar, newLength);
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, newLength);
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    appendTo.append(buffer, (int32_t) wcslen(buffer));
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (buffer != stackBuffer) {
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(buffer);
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const DWORD tfFlags[] = {0, 0, 0, TIME_NOSECONDS};
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::formatTime(const SYSTEMTIME *st, UnicodeString &appendTo) const
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar stackBuffer[STACK_BUFFER_SIZE];
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *buffer = stackBuffer;
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, STACK_BUFFER_SIZE);
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result == 0) {
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int newLength = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, NULL, 0);
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buffer = NEW_ARRAY(UChar, newLength);
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            GetDateFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, newLength);
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    appendTo.append(buffer, (int32_t) wcslen(buffer));
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (buffer != stackBuffer) {
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(buffer);
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString Win32DateFormat::setTimeZoneInfo(TIME_ZONE_INFORMATION *tzi, const TimeZone &zone) const
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString zoneID;
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    zone.getID(zoneID);
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (zoneID.compare(fZoneID) != 0) {
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString icuid;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        zone.getID(icuid);
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (! uprv_getWindowsTimeZoneInfo(tzi, icuid.getBuffer(), icuid.length())) {
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UBool found = FALSE;
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ec = TimeZone::countEquivalentIDs(icuid);
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int z = 0; z < ec; z += 1) {
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString equiv = TimeZone::getEquivalentID(icuid, z);
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (found = uprv_getWindowsTimeZoneInfo(tzi, equiv.getBuffer(), equiv.length())) {
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (! found) {
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                GetTimeZoneInformation(tzi);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return zoneID;
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#endif // U_PLATFORM_HAS_WIN32_API
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323