1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 **********************************************************************
5 * Copyright (c) 2010-2016,International Business Machines
6 * Corporation and others.  All Rights Reserved.
7 **********************************************************************
8 **********************************************************************
9 */
10 
11 #ifndef _DTFMTRTPERF_H
12 #define _DTFMTRTPERF_H
13 
14 #include "unicode/utypes.h"
15 #include "unicode/uperf.h"
16 #include "unicode/timezone.h"
17 #include "unicode/simpletz.h"
18 #include "unicode/calendar.h"
19 #include "unicode/strenum.h"
20 #include "unicode/smpdtfmt.h"
21 #include "unicode/uchar.h"
22 #include "unicode/basictz.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 
26 #include "unicode/uperf.h"
27 #include "unicode/unistr.h"
28 #include "unicode/datefmt.h"
29 #include "unicode/calendar.h"
30 #include "unicode/uclean.h"
31 #include "unicode/brkiter.h"
32 #include "util.h"
33 
34 static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VVVV"};
35 static const int NUM_PATTERNS = UPRV_LENGTHOF(PATTERNS);
36 
37 #include <iostream>
38 #include <stdlib.h>
39 #include <fstream>
40 #include <string>
41 using namespace std;
42 
43 //  Stubs for Windows API functions when building on UNIXes.
44 //
45 #if U_PLATFORM_USES_ONLY_WIN32_API
46 // do nothing
47 #else
48 #define _UNICODE
49 typedef int DWORD;
50 inline int FoldStringW(DWORD dwMapFlags, const UChar* lpSrcStr,int cchSrc, UChar* lpDestStr,int cchDest);
51 #endif
52 
53 class DateTimeRoundTripFunction : public UPerfFunction
54 {
55 private:
56 	int nLocales;
57 public:
58 
DateTimeRoundTripFunction()59 	DateTimeRoundTripFunction()
60 	{
61 		nLocales = 0;
62 	}
63 
DateTimeRoundTripFunction(int locs)64 	DateTimeRoundTripFunction(int locs)
65 	{
66 		nLocales = locs;
67 	}
68 
call(UErrorCode * status)69 	virtual void call(UErrorCode* status)
70 	{
71         *status = U_ZERO_ERROR;
72 
73         SimpleTimeZone unknownZone(-31415, (UnicodeString)"Etc/Unknown");
74         int32_t badDstOffset = -1234;
75         int32_t badZoneOffset = -2345;
76 
77         int32_t testDateData[][3] = {
78             {2007, 1, 15},
79             {2007, 6, 15},
80             {1990, 1, 15},
81             {1990, 6, 15},
82             {1960, 1, 15},
83             {1960, 6, 15},
84         };
85 
86         Calendar *cal = Calendar::createInstance(*status);
87         if (U_FAILURE(*status)) {
88             //dataerrln("Calendar::createInstance failed: %s", u_errorName(*status));
89             return;
90         }
91 
92         // Set up rule equivalency test range
93         UDate low, high;
94         cal->set(1900, UCAL_JANUARY, 1);
95         low = cal->getTime(*status);
96         cal->set(2040, UCAL_JANUARY, 1);
97         high = cal->getTime(*status);
98         if (U_FAILURE(*status)) {
99             //errln("getTime failed");
100             return;
101         }
102 
103         // Set up test dates
104         UDate DATES[UPRV_LENGTHOF(testDateData)/3];
105         const int32_t nDates = UPRV_LENGTHOF(testDateData)/3;
106         cal->clear();
107         for (int32_t i = 0; i < nDates; i++) {
108             cal->set(testDateData[i][0], testDateData[i][1], testDateData[i][2]);
109             DATES[i] = cal->getTime(*status);
110             if (U_FAILURE(*status)) {
111                 //errln("getTime failed");
112                 return;
113             }
114         }
115 
116         // Set up test locales
117         const Locale testLocales[] = {
118             Locale("en"),
119             Locale("en_US"),
120             Locale("en_AU"),
121             Locale("de_DE"),
122             Locale("fr"),
123             Locale("ja_JP"),
124             Locale("ko"),
125             Locale("pt"),
126             Locale("th_TH"),
127             Locale("zh_Hans"),
128 
129             Locale("it"),
130 
131             Locale("en"),
132             Locale("en_US"),
133             Locale("en_AU"),
134             Locale("de_DE"),
135             Locale("fr"),
136             Locale("ja_JP"),
137             Locale("ko"),
138             Locale("pt"),
139             Locale("th_TH"),
140             Locale("zh_Hans"),
141         };
142 
143         const Locale *LOCALES;
144         LOCALES = testLocales;
145 
146         StringEnumeration *tzids = TimeZone::createEnumeration();
147         if (U_FAILURE(*status)) {
148             //errln("tzids->count failed");
149             return;
150         }
151 
152         // Run the roundtrip test
153         for (int32_t locidx = 0; locidx < nLocales; locidx++) {
154             for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) {
155                 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)PATTERNS[patidx], LOCALES[locidx], *status);
156                 if (U_FAILURE(*status)) {
157                     //errcheckln(*status, (UnicodeString)"new SimpleDateFormat failed for pattern " +
158                     //    PATTERNS[patidx] + " for locale " + LOCALES[locidx].getName() + " - " + u_errorName(*status));
159                     *status = U_ZERO_ERROR;
160                     continue;
161                 }
162 
163                 tzids->reset(*status);
164                 const UnicodeString *tzid;
165                 while ((tzid = tzids->snext(*status))) {
166                     TimeZone *tz = TimeZone::createTimeZone(*tzid);
167 
168                     for (int32_t datidx = 0; datidx < nDates; datidx++) {
169                         UnicodeString tzstr;
170                         FieldPosition fpos(FieldPosition::DONT_CARE);
171 
172                         // Format
173                         sdf->setTimeZone(*tz);
174                         sdf->format(DATES[datidx], tzstr, fpos);
175 
176                         // Before parse, set unknown zone to SimpleDateFormat instance
177                         // just for making sure that it does not depends on the time zone
178                         // originally set.
179                         sdf->setTimeZone(unknownZone);
180 
181                         // Parse
182                         ParsePosition pos(0);
183                         Calendar *outcal = Calendar::createInstance(unknownZone, *status);
184                         if (U_FAILURE(*status)) {
185                             //errln("Failed to create an instance of calendar for receiving parse result.");
186                             *status = U_ZERO_ERROR;
187                             continue;
188                         }
189                         outcal->set(UCAL_DST_OFFSET, badDstOffset);
190                         outcal->set(UCAL_ZONE_OFFSET, badZoneOffset);
191                         sdf->parse(tzstr, *outcal, pos);
192 
193                         // clean loop
194                         delete outcal;
195 
196                     }
197                     delete tz;
198                     // break  time zone loop
199                     break;
200 
201                 }
202                 delete sdf;
203             }
204         }
205         delete cal;
206         delete tzids;
207 
208 	}
209 
getOperationsPerIteration()210 	virtual long getOperationsPerIteration()
211 	{
212 		return NUM_PATTERNS * nLocales * 6;
213 	}
214 };
215 
216 
217 class DateTimeRoundTripPerfTest : public UPerfTest
218 {
219 private:
220 
221 public:
222 
223 	DateTimeRoundTripPerfTest(int32_t argc, const char* argv[], UErrorCode& status);
224 	~DateTimeRoundTripPerfTest();
225 	virtual UPerfFunction* runIndexedTest(int32_t index, UBool exec,const char* &name, char* par);
226 
227 	UPerfFunction* RoundTripLocale1();
228 	UPerfFunction* RoundTripLocale10();
229 	UPerfFunction* RoundTripLocale11();
230 	UPerfFunction* RoundTripLocale21();
231 };
232 
233 
234 #endif // DateTimeRoundTripPerfTest
235