164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
58de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert*   Copyright (C) 2005-2016, International Business Machines
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File WINDTFMT.CPP
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1683a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#if U_PLATFORM_HAS_WIN32_API
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/format.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/fmtable.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/datefmt.h"
248de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert#include "unicode/simpleformatter.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/calendar.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/gregocal.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/locid.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unistr.h"
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/timezone.h"
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utmscale.h"
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uresimp.h"
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "windtfmt.h"
3685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "wintzimpl.h"
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define WIN32_LEAN_AND_MEAN
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define VC_EXTRALEAN
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOUSER
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOSERVICE
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOIME
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOMCX
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <windows.h>
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32DateFormat)
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}"
738de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        return new UnicodeString(defaultPattern, UPRV_LENGTHOF(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
1271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    this->fDateTimeMsg = other.fDateTimeMsg == NULL ? NULL : new UnicodeString(*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) {
1708de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        UnicodeString date;
1718de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        UnicodeString time;
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString *pattern = fDateTimeMsg;
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1748de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        formatDate(&st_local, date);
1758de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        formatTime(&st_local, time);
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (strcmp(fCalendar->getType(), cal.getType()) != 0) {
17859d709d503bab6e2b61931737e662dd293b40578ccornelius            pattern = getTimeDateFormat(&cal, &fLocale, status);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1818de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        SimpleFormatter(*pattern, 2, 2, status).format(time, date, appendTo, status);
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (fDateStyle != DateFormat::kNone) {
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatDate(&st_local, appendTo);
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (fTimeStyle != DateFormat::kNone) {
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        formatTime(&st_local, appendTo);
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& pos) const
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pos.setErrorIndex(pos.getIndex());
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::adoptCalendar(Calendar *newCalendar)
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fCalendar == NULL || strcmp(fCalendar->getType(), newCalendar->getType()) != 0) {
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) {
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete fDateTimeMsg;
20359d709d503bab6e2b61931737e662dd293b40578ccornelius            fDateTimeMsg = getTimeDateFormat(newCalendar, &fLocale, status);
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete fCalendar;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar = newCalendar;
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, fCalendar->getTimeZone());
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::setCalendar(const Calendar &newCalendar)
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    adoptCalendar(newCalendar.clone());
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::adoptTimeZone(TimeZone *zoneToAdopt)
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, *zoneToAdopt);
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->adoptTimeZone(zoneToAdopt);
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::setTimeZone(const TimeZone& zone)
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fZoneID = setTimeZoneInfo(fTZI, zone);
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fCalendar->setTimeZone(zone);
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const DWORD dfFlags[] = {DATE_LONGDATE, DATE_LONGDATE, DATE_SHORTDATE, DATE_SHORTDATE};
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::formatDate(const SYSTEMTIME *st, UnicodeString &appendTo) const
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
23564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    wchar_t stackBuffer[STACK_BUFFER_SIZE];
23664339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    wchar_t *buffer = stackBuffer;
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, STACK_BUFFER_SIZE);
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result == 0) {
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int newLength = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, NULL, 0);
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            buffer = NEW_ARRAY(wchar_t, newLength);
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, newLength);
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24964339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    appendTo.append((const UChar *)buffer, (int32_t) wcslen(buffer));
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (buffer != stackBuffer) {
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(buffer);
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const DWORD tfFlags[] = {0, 0, 0, TIME_NOSECONDS};
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32DateFormat::formatTime(const SYSTEMTIME *st, UnicodeString &appendTo) const
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
26164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    wchar_t stackBuffer[STACK_BUFFER_SIZE];
26264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    wchar_t *buffer = stackBuffer;
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, STACK_BUFFER_SIZE);
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result == 0) {
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int newLength = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, NULL, 0);
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27064339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert            buffer = NEW_ARRAY(wchar_t, newLength);
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            GetDateFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, newLength);
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    appendTo.append((const UChar *)buffer, (int32_t) wcslen(buffer));
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (buffer != stackBuffer) {
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(buffer);
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString Win32DateFormat::setTimeZoneInfo(TIME_ZONE_INFORMATION *tzi, const TimeZone &zone) const
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString zoneID;
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    zone.getID(zoneID);
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (zoneID.compare(fZoneID) != 0) {
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString icuid;
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        zone.getID(icuid);
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (! uprv_getWindowsTimeZoneInfo(tzi, icuid.getBuffer(), icuid.length())) {
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UBool found = FALSE;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ec = TimeZone::countEquivalentIDs(icuid);
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int z = 0; z < ec; z += 1) {
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString equiv = TimeZone::getEquivalentID(icuid, z);
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (found = uprv_getWindowsTimeZoneInfo(tzi, equiv.getBuffer(), equiv.length())) {
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (! found) {
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                GetTimeZoneInformation(tzi);
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return zoneID;
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31783a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#endif // U_PLATFORM_HAS_WIN32_API
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319