1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "measure_data.h"
16 #include <string>
17 #include <unordered_map>
18 #include <cmath>
19 #include "utils.h"
20 
21 namespace OHOS {
22 namespace Global {
23 namespace I18n {
24 using namespace std;
25 const double FT_TO_M = 0.3048;
26 const double FT2_TO_M2 = FT_TO_M * FT_TO_M;
27 const double FT3_TO_M3 = FT_TO_M * FT2_TO_M2;
28 const double IN3_TO_M3 = FT3_TO_M3 / (12 * 12 * 12);
29 const double GAL_IMP_TO_M3 = 0.00454609;
30 const double GAL_TO_M3 = 231 * IN3_TO_M3;
31 const int REGION_OFFSET = 7;
32 const int BASE_VALUE_SIZE = 2;
33 const int FACTOR_SIZE = 2;
34 const int CHAR_OFFSET = 48;
35 const int MAX_UNIT_NUM = 500;
36 
37 const std::unordered_map<std::string, std::vector<std::string>> USAGE_001 {
38     { "area-land-agricult", { "hectare" } },
39     { "area-land-commercl", { "hectare" } },
40     { "area-land-residntl", { "hectare" } },
41     { "length-person", { "centimeter" } },
42     { "length-person-small", { "centimeter" } },
43     { "length-rainfall", { "millimeter" } },
44     { "length-road", { "meter" } },
45     { "length-road-small", { "meter" } },
46     { "length-snowfall", { "centimeter" } },
47     { "length-vehicle", { "meter" } },
48     { "length-visiblty", { "meter" } },
49     { "length-visiblty-small", { "meter" } },
50     { "speed-road-travel", { "kilometer-per-hour" } },
51     { "speed-wind", { "kilometer-per-hour" } },
52     { "temperature-person", { "celsius" } },
53     { "temperature-weather", { "celsius" } },
54     { "volume-vehicle-fuel", { "liter" } },
55 };
56 
57 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_001 {
58     { "length", { "kilometer", "meter", "centimeter" } },
59     { "area", { "square-kilometer", "hectare", "square-meter", "square-centimeter" } },
60     { "speed", { "kilometer-per-hour" } },
61     { "temperature", { "celsius" } },
62     { "volume", { "cubic-meter", "cubic-centimeter" } },
63 };
64 
65 const std::unordered_map<std::string, std::vector<std::string>> USAGE_AT {
66     { "length-person", { "meter", "centimeter" } },
67 };
68 
69 const std::unordered_map<std::string, std::vector<std::string>> USAGE_BR {
70     { "length-person-informal", { "meter", "centimeter" } },
71     { "length-rainfall", { "centimeter" } },
72 };
73 
74 const std::unordered_map<std::string, std::vector<std::string>> USAGE_BS {
75     { "temperature-weather", { "fahrenheit" } },
76 };
77 
78 const std::unordered_map<std::string, std::vector<std::string>> USAGE_CA {
79     { "length-person", { "inch" } },
80     { "length-person-informal", { "foot", "inch" } },
81     { "length-person-small-informal", { "inch" } },
82 };
83 
84 const std::unordered_map<std::string, std::vector<std::string>> USAGE_CN {
85     { "length-person-informal", { "meter", "centimeter" } },
86 };
87 
88 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DE {
89     { "length-person-informal", { "meter", "centimeter" } },
90     { "length-visiblty", { "meter" } },
91 };
92 
93 const std::unordered_map<std::string, std::vector<std::string>> USAGE_GB {
94     { "area-land-agricult", { "acre" } },
95     { "area-land-commercl", { "acre" } },
96     { "area-land-residntl", { "acre" } },
97     { "length-person", { "inch" } },
98     { "length-person-informal", { "foot", "inch" } },
99     { "length-person-small-informal", { "inch" } },
100     { "length-road", { "yard" } },
101     { "length-road-small", { "yard" } },
102     { "length-vehicle", { "foot", "inch" } },
103     { "length-visiblty", { "mile", "foot" } },
104     { "length-visiblty-small", { "foot" } },
105     { "speed-road-travel", { "mile-per-hour" } },
106 };
107 
108 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_GB {
109     { "length", { "mile", "foot", "inch" } },
110     { "area", { "square-mile", "acre", "square-foot", "square-inch" } },
111     { "speed", { "mile-per-hour" } },
112     { "volume", { "cubic-foot", "cubic-inch" } },
113 };
114 
115 const std::unordered_map<std::string, std::vector<std::string>> USAGE_KR {
116     { "speed-wind", { "meter-per-second" } },
117 };
118 
119 const std::unordered_map<std::string, std::vector<std::string>> USAGE_MX {
120     { "length-person-informal", { "meter", "centimeter" } },
121     { "length-vehicle", { "meter", "centimeter" } },
122 };
123 
124 const std::unordered_map<std::string, std::vector<std::string>> USAGE_NL {
125     { "length-person-informal", { "meter", "centimeter" } },
126     { "length-visiblty", { "meter" } },
127 };
128 
129 const std::unordered_map<std::string, std::vector<std::string>> USAGE_NO {
130     { "length-person-informal", { "meter", "centimeter" } },
131     { "speed-wind", { "meter-per-second" } },
132 };
133 
134 const std::unordered_map<std::string, std::vector<std::string>> USAGE_SE {
135     { "length-person", { "meter", "centimeter" } },
136     { "length-road", { "mile-scandinavian", "kilometer" } },
137     { "length-road-informal", { "mile-scandinavian" } },
138     { "speed-wind", { "meter-per-second" } },
139 };
140 
141 const std::unordered_map<std::string, std::vector<std::string>> USAGE_US {
142     { "area-land-agricult", { "acre" } },
143     { "area-land-commercl", { "acre" } },
144     { "area-land-residntl", { "acre" } },
145     { "length-person", { "inch" } },
146     { "length-person-informal", { "foot", "inch" } },
147     { "length-person-small", { "inch" } },
148     { "length-rainfall", { "inch" } },
149     { "length-road", { "mile" } },
150     { "length-road-small", { "foot" } },
151     { "length-snowfall", { "inch" } },
152     { "length-vehicle", { "foot", "inch" } },
153     { "length-visiblty", { "mile", "foot" } },
154     { "length-visiblty-small", { "foot" } },
155     { "speed-road-travel", { "mile-per-hour" } },
156     { "speed-wind", { "mile-per-hour" } },
157     { "temperature-person", { "fahrenheit" } },
158     { "temperature-weather", { "fahrenheit" } },
159     { "volume-vehicle-fuel", { "gallon" } },
160 };
161 
162 const std::unordered_map<std::string, std::vector<std::string>> USAGE_DEFAULT_US {
163     { "length", { "mile", "foot", "inch" } },
164     { "area", { "square-mile", "acre", "square-foot", "square-inch" } },
165     { "speed", { "mile-per-hour" } },
166     { "temperature", { "fahrenheit" } },
167     { "volume", { "cubic-foot", "cubic-inch" } },
168 };
169 
170 const std::unordered_map<std::string, std::vector<double>> CONVERT_FACTORS {
171     { "acre", { FT2_TO_M2 * 43560, 0 } },
172     { "hectare", { 10000, 0 } },
173     { "dunam", { 1000, 0 } },
174     { "fathom", { FT_TO_M * 6, 0 } },
175     { "foot", { FT_TO_M, 0 } },
176     { "furlong", { FT_TO_M * 660, 0 } },
177     { "inch", { FT_TO_M / 12, 0 } },
178     { "meter", { 1, 0 } },
179     { "mile", { FT_TO_M * 5280, 0 } },
180     { "mile-scandinavian", { 10000, 0 } },
181     { "nautical-mile", { 1852, 0 } },
182     { "point", { FT_TO_M / 864, 0 } },
183     { "yard", { FT_TO_M * 3, 0 } },
184     { "knot", { 1852 / 3600.0, 0 } },
185     { "kilometer-per-hour", { 1000 / 3600.0, 0 } },
186     { "celsius", { 1, 273.15 }},
187     { "fahrenheit", {5.0 / 9, 2298.35 / 9 }},
188     { "kelvin", { 1, 0 } },
189     { "acre-foot", { 43560 * FT3_TO_M3, 0 } },
190     { "bushel", { GAL_IMP_TO_M3 * 8, 0 } },
191     { "bushel-UK", { GAL_IMP_TO_M3 * 8, 0 } },
192     { "bushel-US", { IN3_TO_M3 * 2150.42, 0 } },
193     { "cup", { GAL_IMP_TO_M3 / 16, 0 } },
194     { "cup-UK", { GAL_IMP_TO_M3 / 16, 0 } },
195     { "cup-US", { GAL_TO_M3 / 16, 0 } },
196     { "cup-metric", {0.00025, 0 } },
197     { "fluid-ounce", { GAL_IMP_TO_M3 / 128, 0 } },
198     { "fluid-ounce-imperial", { GAL_IMP_TO_M3 / 160, 0 } },
199     { "gallon", { GAL_TO_M3, 0 } },
200     { "gallon-imperial", { GAL_IMP_TO_M3, 0 } },
201     { "liter", {0.001, 0 } },
202     { "pint-metric", { 0.0005, 0 } },
203     { "pint", { GAL_IMP_TO_M3 / 8, 0 } },
204     { "pint-UK", { GAL_IMP_TO_M3 / 8, 0 } },
205     { "pint-US", { GAL_TO_M3 / 8, 0 } },
206     { "quart", { GAL_IMP_TO_M3 / 4, 0 } },
207     { "quart-UK", { GAL_IMP_TO_M3 / 4, 0 } },
208     { "quart-US", { GAL_TO_M3 / 4, 0 } },
209     { "tablespoon", { GAL_IMP_TO_M3 / 256, 0 } },
210     { "tablespoon-UK", { GAL_IMP_TO_M3 / 256, 0 } },
211     { "tablespoon-US", { GAL_TO_M3 / 256, 0 } },
212     { "teaspoon", { GAL_IMP_TO_M3 / (16 * 48), 0 } },
213     { "teaspoon-UK", { GAL_IMP_TO_M3 / (16 * 48), 0 } },
214     { "teaspoon-US", { GAL_TO_M3 / (16 * 48), 0 } },
215     { "barrel", { GAL_IMP_TO_M3 * 36, 0 } },
216     { "barrel-UK", { GAL_IMP_TO_M3 * 36, 0 } },
217     { "barrel-US", { GAL_TO_M3 * 42, 0 } },
218     { "hour", { 3600, 0 } },
219     { "second", { 1, 0 } },
220 };
221 
222 const std::unordered_map<std::string, std::string> CONVERT_TO_UNIT {
223     { "acre", "square-meter" },
224     { "hectare", "square-meter" },
225     { "dunam", "square-meter" },
226     { "fathom", "meter" },
227     { "foot", "meter" },
228     { "furlong", "meter" },
229     { "inch", "meter" },
230     { "meter", "meter" },
231     { "mile", "meter" },
232     { "mile-scandinavian", "meter" },
233     { "nautical-mile", "meter" },
234     { "point", "meter" },
235     { "yard", "meter" },
236     { "knot", "meter-per-second" },
237     { "kilometer-per-hour", "meter-per-second" },
238     { "celsius", "kelvin" },
239     { "fahrenheit", "kelvin" },
240     { "kelvin", "kelvin" },
241     { "acre-foot", "cubic-meter" },
242     { "bushel", "cubic-meter" },
243     { "bushel-UK", "cubic-meter" },
244     { "bushel-US", "cubic-meter" },
245     { "cup", "cubic-meter" },
246     { "cup-UK", "cubic-meter" },
247     { "cup-US", "cubic-meter" },
248     { "cup-metric", "cubic-meter" },
249     { "fluid-ounce", "cubic-meter" },
250     { "fluid-ounce-imperial", "cubic-meter" },
251     { "gallon", "cubic-meter" },
252     { "gallon-imperial", "cubic-meter" },
253     { "liter", "cubic-meter" },
254     { "pint-metric", "cubic-meter" },
255     { "pint", "cubic-meter" },
256     { "pint-UK", "cubic-meter" },
257     { "pint-US", "cubic-meter" },
258     { "quart", "cubic-meter" },
259     { "quart-UK", "cubic-meter" },
260     { "quart-US", "cubic-meter" },
261     { "tablespoon", "cubic-meter" },
262     { "tablespoon-UK", "cubic-meter" },
263     { "tablespoon-US", "cubic-meter" },
264     { "teaspoon", "cubic-meter" },
265     { "teaspoon-UK", "cubic-meter" },
266     { "teaspoon-US", "cubic-meter" },
267     { "barrel", "cubic-meter" },
268     { "barrel-US", "cubic-meter" },
269     { "barrel-UK", "cubic-meter" },
270     { "hour", "second" },
271     { "second", "second" },
272 };
273 
274 const std::unordered_map<std::string, double> PREFIX_VALUE {
275     { "deci", pow(10, -1) },
276     { "centi", pow(10, -2) },
277     { "milli", pow(10, -3) },
278     { "micro", pow(10, -6) },
279     { "nano", pow(10, -9) },
280     { "pico", pow(10, -12) },
281     { "kilo", pow(10, 3) },
282     { "hecto", pow(10, 2) },
283     { "mega", pow(10, 6) },
284 };
285 
286 const std::vector<std::string> BYTE_VALUE {
287     "byte",
288     "kilobyte",
289     "megabyte",
290     "gigabyte",
291     "terabyte",
292     "petabyte"
293 };
294 
295 const std::vector<std::pair<std::string, double>> DATE_VALUE {
296     { "second", 1 },
297     { "minute", 60 },
298     { "hour", 60 },
299     { "day", 24},
300     { "month", 30 },
301     { "year", 365 / 30 }
302 };
303 
304 const std::unordered_map<std::string, double> POWER_VALUE {
305     { "square-", 2 },
306     { "cubic-", 3 },
307 };
308 
GetMask(const string & region)309 uint32_t GetMask(const string &region)
310 {
311     uint32_t firstChar = (region.c_str()[0] - CHAR_OFFSET);
312     uint32_t secondChar = (region.c_str()[1] - CHAR_OFFSET);
313     return (firstChar << REGION_OFFSET) | secondChar;
314 }
315 
GetDefaultPreferredUnit(const string & region,const string & type,vector<string> & units)316 void GetDefaultPreferredUnit(const string &region, const string &type, vector<string> &units)
317 {
318     switch (GetMask(region)) {
319         case 0x00000B92: {
320             if (USAGE_DEFAULT_GB.count(type) > 0) {
321                 units.assign(USAGE_DEFAULT_GB.at(type).begin(), USAGE_DEFAULT_GB.at(type).end());
322             }
323             break;
324         }
325         case 0x000012A3: {
326             if (USAGE_DEFAULT_US.count(type) > 0) {
327                 units.assign(USAGE_DEFAULT_US.at(type).begin(), USAGE_DEFAULT_US.at(type).end());
328             }
329             break;
330         }
331         default: {
332             if (USAGE_DEFAULT_001.count(type) > 0) {
333                 units.assign(USAGE_DEFAULT_001.at(type).begin(), USAGE_DEFAULT_001.at(type).end());
334             }
335             break;
336         }
337     }
338 }
339 
GetFallbackPreferredUnit(const string & region,const string & usage,vector<string> & units)340 void GetFallbackPreferredUnit(const string &region, const string &usage, vector<string> &units)
341 {
342     switch (GetMask(region)) {
343         case 0x00000EA8: {
344             if (USAGE_MX.count(usage) > 0) {
345                 units.assign(USAGE_MX.at(usage).begin(), USAGE_MX.at(usage).end());
346                 return;
347             }
348             break;
349         }
350         case 0x00000F1C: {
351             if (USAGE_NL.count(usage) > 0) {
352                 units.assign(USAGE_NL.at(usage).begin(), USAGE_NL.at(usage).end());
353                 return;
354             }
355             break;
356         }
357         case 0x00000F1F:
358         case 0x0000101C:
359         case 0x00001125: {
360             if (USAGE_NO.count(usage) > 0) {
361                 units.assign(USAGE_NO.at(usage).begin(), USAGE_NO.at(usage).end());
362                 return;
363             }
364             break;
365         }
366         case 0x00001195: {
367             if (USAGE_SE.count(usage) > 0) {
368                 units.assign(USAGE_SE.at(usage).begin(), USAGE_SE.at(usage).end());
369                 return;
370             }
371             break;
372         }
373         case 0x000012A3: {
374             if (USAGE_US.count(usage) > 0) {
375                 units.assign(USAGE_US.at(usage).begin(), USAGE_US.at(usage).end());
376                 return;
377             }
378             break;
379         }
380         default: {
381             if (USAGE_001.count(usage) > 0) {
382                 units.assign(USAGE_001.at(usage).begin(), USAGE_001.at(usage).end());
383                 return;
384             }
385             break;
386         }
387     }
388 }
389 
GetRestPreferredUnit(const string & region,const string & usage,vector<string> & units)390 void GetRestPreferredUnit(const string &region, const string &usage, vector<string> &units)
391 {
392     switch (GetMask(region)) {
393         case 0x00000991:
394         case 0x00000C9E: {
395             if (USAGE_CA.count(usage) > 0) {
396                 units.assign(USAGE_CA.at(usage).begin(), USAGE_CA.at(usage).end());
397                 return;
398             }
399             break;
400         }
401         case 0x0000099E:
402         case 0x00000A1B:
403         case 0x00001024: {
404             if (USAGE_CN.count(usage) > 0) {
405                 units.assign(USAGE_CN.at(usage).begin(), USAGE_CN.at(usage).end());
406                 return;
407             }
408             break;
409         }
410         case 0x00000A15: {
411             if (USAGE_DE.count(usage) > 0) {
412                 units.assign(USAGE_DE.at(usage).begin(), USAGE_DE.at(usage).end());
413                 return;
414             }
415             break;
416         }
417         case 0x00000B92: {
418             if (USAGE_GB.count(usage) > 0) {
419                 units.assign(USAGE_GB.at(usage).begin(), USAGE_GB.at(usage).end());
420                 return;
421             }
422             break;
423         }
424         case 0x00000DA2: {
425             if (USAGE_KR.count(usage) > 0) {
426                 units.assign(USAGE_KR.at(usage).begin(), USAGE_KR.at(usage).end());
427                 return;
428             }
429             break;
430         }
431         default: {
432             GetFallbackPreferredUnit(region, usage, units);
433             break;
434         }
435     }
436     if (!units.size()) {
437         GetDefaultPreferredUnit(region, usage, units);
438     }
439 }
440 
GetPreferredUnit(const string & region,const string & usage,vector<string> & units)441 void GetPreferredUnit(const string &region, const string &usage, vector<string> &units)
442 {
443     switch (GetMask(region)) {
444         case 0x000008A4:
445         case 0x00000915:
446         case 0x00000A2A:
447         case 0x00000A97:
448         case 0x00000AA3:
449         case 0x00000B22:
450         case 0x00000C1B:
451         case 0x00000C94:
452         case 0x00000C9C:
453         case 0x00000CA4:
454         case 0x00000D1F:
455         case 0x00000EA9:
456         case 0x00001191:
457         case 0x00001222:
458         case 0x0000131E: {
459             if (USAGE_AT.count(usage) > 0) {
460                 units.assign(USAGE_AT.at(usage).begin(), USAGE_AT.at(usage).end());
461                 return;
462             }
463             break;
464         }
465         case 0x00000922: {
466             if (USAGE_BR.count(usage) > 0) {
467                 units.assign(USAGE_BR.at(usage).begin(), USAGE_BR.at(usage).end());
468                 return;
469             }
470             break;
471         }
472         case 0x00000923:
473         case 0x0000092A:
474         case 0x00001022:
475         case 0x00001027: {
476             if (USAGE_BS.count(usage) > 0) {
477                 units.assign(USAGE_BS.at(usage).begin(), USAGE_BS.at(usage).end());
478                 return;
479             }
480             break;
481         }
482         default: {
483             GetRestPreferredUnit(region, usage, units);
484             break;
485         }
486     }
487     if (!units.size()) {
488         GetRestPreferredUnit(region, usage, units);
489     }
490 }
491 
ComputeFactorValue(const string & unit,const string & measSys,vector<double> & factors)492 void ComputeFactorValue(const string &unit, const string &measSys, vector<double> &factors)
493 {
494     string unitKey = unit + "-" + measSys;
495     if (CONVERT_FACTORS.count(unitKey) > 0) {
496         factors[0] = CONVERT_FACTORS.at(unitKey)[0];
497         factors[1] = CONVERT_FACTORS.at(unitKey)[1];
498         return;
499     }
500     if (CONVERT_FACTORS.count(unit) > 0) {
501         factors[0] = CONVERT_FACTORS.at(unit)[0];
502         factors[1] = CONVERT_FACTORS.at(unit)[1];
503     }
504 }
505 
ComputeSIPrefixValue(const string & unit)506 double ComputeSIPrefixValue(const string &unit)
507 {
508     for (auto& prefixValue : PREFIX_VALUE) {
509         if (!unit.rfind(prefixValue.first, 0)) {
510             return prefixValue.second;
511         }
512     }
513     return 0.0;
514 }
515 
ComputePowerValue(const string & unit,const string & measSys,vector<double> & factors)516 void ComputePowerValue(const string &unit, const string &measSys, vector<double> &factors)
517 {
518     for (auto& powerValue : POWER_VALUE) {
519         if (!unit.rfind(powerValue.first, 0)) {
520             string baseUnit = unit.substr(powerValue.first.length());
521             double value = ComputeSIPrefixValue(baseUnit);
522             double compare = 0.0;
523             if (fabs(value - compare) < 1e-6) {
524                 ComputeFactorValue(baseUnit, measSys, factors);
525             }
526             factors[0] = pow(factors[0], powerValue.second);
527         }
528     }
529 }
530 
ComputeValue(const string & unit,const string & measSys,vector<double> & factors)531 int ComputeValue(const string &unit, const string &measSys, vector<double> &factors)
532 {
533     if (unit.find("-per-") != string::npos) {
534         vector<string> baseValues;
535         Split(unit, "-per-", baseValues);
536         if (baseValues.size() == BASE_VALUE_SIZE) {
537             vector<double> numerator = { 1.0, 0.0 };
538             int status = ComputeValue(baseValues[0], measSys, numerator);
539             if (!status) {
540                 return 0;
541             }
542             vector<double> denominator = { 1.0, 0.0 };
543             status = ComputeValue(baseValues[1], measSys, denominator);
544             if (!status) {
545                 return 0;
546             }
547             factors[0] = numerator[0] / denominator[0];
548             return 1;
549         }
550     }
551     double compare = 0.0;
552     factors[0] = ComputeSIPrefixValue(unit);
553     if (fabs(factors[0] - compare) < 1e-6) {
554         ComputePowerValue(unit, measSys, factors);
555     }
556     if (fabs(factors[0] - compare) < 1e-6) {
557         ComputeFactorValue(unit, measSys, factors);
558     }
559     if (fabs(factors[0] - compare) < 1e-6) {
560         factors[0] = 1.0;
561         return 0;
562     }
563     return 1;
564 }
565 
ConvertByte(double & number,std::string & unit)566 bool ConvertByte(double& number, std::string& unit)
567 {
568     double tempNumber = number;
569     if (tempNumber < 0) {
570         tempNumber *= -1;
571     }
572     std::string tempUnit = unit;
573     int indexFirst = -1;
574     for (size_t i = 0; i < BYTE_VALUE.size(); i++) {
575         if (BYTE_VALUE[i] == tempUnit) {
576             indexFirst = static_cast<int>(i);
577             break;
578         }
579     }
580     bool status = (indexFirst >= 0);
581     size_t indexSecond = status ? static_cast<size_t>(indexFirst) : 0;
582     for (size_t i = indexSecond; i > 0; i--) {
583         if (tempNumber < 1) {
584             // 10 ^ 3 is the threshold for carry
585             tempNumber *= pow(10, 3);
586             tempUnit = BYTE_VALUE[i - 1];
587             indexSecond = i - 1;
588         }
589     }
590 
591     for (size_t i = indexSecond + 1; i < BYTE_VALUE.size(); i++) {
592         // 900 is the threshold for carry
593         if (tempNumber > 900) {
594             // 10 ^ 3 is the threshold for carry
595             tempNumber /= pow(10, 3);
596             tempUnit = BYTE_VALUE[i];
597         } else {
598             break;
599         }
600     }
601 
602     if (status) {
603         number = tempNumber;
604         unit = tempUnit;
605         return true;
606     }
607     return false;
608 }
609 
ConvertDate(double & number,std::string & unit)610 bool ConvertDate(double& number, std::string& unit)
611 {
612     double tempNumber = number;
613     if (tempNumber < 0) {
614         tempNumber *= -1;
615     }
616     std::string tempUnit = unit;
617 
618     int indexFirst = -1;
619     for (size_t i = 0; i < DATE_VALUE.size(); i++) {
620         if (DATE_VALUE[i].first == tempUnit) {
621             indexFirst = static_cast<int>(i);
622             break;
623         }
624     }
625     bool status = (indexFirst >= 0);
626     size_t indexSecond = status ? static_cast<size_t>(indexFirst) : 0;
627     for (size_t i = indexSecond; i > 0; i--) {
628         if (tempNumber < 1) {
629             tempNumber *= DATE_VALUE[i].second;
630             tempUnit = DATE_VALUE[i - 1].first;
631             indexSecond = i - 1;
632         }
633     }
634 
635     for (size_t i = indexSecond + 1; i < DATE_VALUE.size(); i++) {
636         if ((tempNumber / DATE_VALUE[i].second) >= 1) {
637             tempNumber /= DATE_VALUE[i].second;
638             tempUnit = DATE_VALUE[i].first;
639         } else {
640             break;
641         }
642     }
643 
644     if (status) {
645         number = floor(tempNumber);
646         number *= -1;
647         unit = tempUnit;
648         return true;
649     }
650     return false;
651 }
652 
Convert(double & value,const string & fromUnit,const string & fromMeasSys,const string & toUnit,const string & toMeasSys)653 int Convert(double &value, const string &fromUnit, const string &fromMeasSys, const string &toUnit,
654     const string &toMeasSys)
655 {
656     double baseResult = 0.0;
657     double result = 0.0;
658     vector<double> fromFactors = {0.0, 0.0};
659     string fromUnitType;
660     string toUnitType;
661     icu::MeasureUnit unitArray[MAX_UNIT_NUM];
662     UErrorCode icuStatus = U_ZERO_ERROR;
663     icu::MeasureUnit::getAvailable(unitArray, MAX_UNIT_NUM, icuStatus);
664     if (!U_SUCCESS(icuStatus)) {
665         return 0;
666     }
667     for (icu::MeasureUnit curUnit : unitArray) {
668         if (!strcmp(curUnit.getSubtype(), fromUnit.c_str())) {
669             fromUnitType = curUnit.getType();
670         }
671         if (!strcmp(curUnit.getSubtype(), toUnit.c_str())) {
672             toUnitType = curUnit.getType();
673         }
674     }
675     if (fromUnitType.empty() || toUnitType.empty() || strcmp(fromUnitType.c_str(), toUnitType.c_str())) {
676         return 0;
677     }
678     int status = ComputeValue(fromUnit, fromMeasSys, fromFactors);
679     if (!status) {
680         return 0;
681     }
682     vector<double> toFactors = {0.0, 0.0};
683     status = ComputeValue(toUnit, toMeasSys, toFactors);
684     if (!status) {
685         return 0;
686     }
687     if (fromFactors.size() == FACTOR_SIZE) {
688         baseResult = fromFactors[0] * value + fromFactors[1];
689     }
690     if (toFactors.size() == FACTOR_SIZE) {
691         result = (baseResult - toFactors[1]) / toFactors[0];
692     }
693     value = result;
694     return 1;
695 }
696 } // namespace I18n
697 } // namespace Global
698 } // namespace OHOS