1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | This source file is subject to version 3.01 of the PHP license,      |
6   | that is bundled with this package in the file LICENSE, and is        |
7   | available through the world-wide-web at the following url:           |
8   | http://www.php.net/license/3_01.txt                                  |
9   | If you did not receive a copy of the PHP license and are unable to   |
10   | obtain it through the world-wide-web, please send a note to          |
11   | license@php.net so we can mail you a copy immediately.               |
12   +----------------------------------------------------------------------+
13   | Authors: Gustavo Lopes <cataphract@php.net>                          |
14   +----------------------------------------------------------------------+
15*/
16
17#ifdef HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include "../intl_cppshims.h"
22
23#include <unicode/locid.h>
24#include <unicode/timezone.h>
25#include <unicode/ustring.h>
26#include "intl_convertcpp.h"
27
28#include "../common/common_date.h"
29
30extern "C" {
31#include "../php_intl.h"
32#define USE_TIMEZONE_POINTER 1
33#include "timezone_class.h"
34#include "intl_convert.h"
35#include <zend_exceptions.h>
36#include <ext/date/php_date.h>
37}
38#include "common/common_enum.h"
39
40U_CFUNC PHP_METHOD(IntlTimeZone, __construct)
41{
42    zend_throw_exception( NULL,
43        "An object of this type cannot be created with the new operator",
44        0 TSRMLS_CC );
45}
46
47U_CFUNC PHP_FUNCTION(intltz_create_time_zone)
48{
49    char    *str_id;
50    int     str_id_len;
51    intl_error_reset(NULL TSRMLS_CC);
52
53    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
54            &str_id, &str_id_len) == FAILURE) {
55        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
56            "intltz_create_time_zone: bad arguments", 0 TSRMLS_CC);
57        RETURN_NULL();
58    }
59
60    UErrorCode status = UErrorCode();
61    UnicodeString id = UnicodeString();
62    if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) {
63        intl_error_set(NULL, status,
64            "intltz_create_time_zone: could not convert time zone id to UTF-16", 0 TSRMLS_CC);
65        RETURN_NULL();
66    }
67
68    //guaranteed non-null; GMT if timezone cannot be understood
69    TimeZone *tz = TimeZone::createTimeZone(id);
70    timezone_object_construct(tz, return_value, 1 TSRMLS_CC);
71}
72
73U_CFUNC PHP_FUNCTION(intltz_from_date_time_zone)
74{
75    zval                *zv_timezone;
76    TimeZone            *tz;
77    php_timezone_obj    *tzobj;
78    intl_error_reset(NULL TSRMLS_CC);
79
80    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
81            &zv_timezone, php_date_get_timezone_ce()) == FAILURE) {
82        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
83            "intltz_from_date_time_zone: bad arguments", 0 TSRMLS_CC);
84        RETURN_NULL();
85    }
86
87    tzobj = (php_timezone_obj *)zend_objects_get_address(zv_timezone TSRMLS_CC);
88    if (!tzobj->initialized) {
89        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
90            "intltz_from_date_time_zone: DateTimeZone object is unconstructed",
91            0 TSRMLS_CC);
92        RETURN_NULL();
93    }
94
95    tz = timezone_convert_datetimezone(tzobj->type, tzobj, FALSE, NULL,
96        "intltz_from_date_time_zone" TSRMLS_CC);
97    if (tz == NULL) {
98        RETURN_NULL();
99    }
100
101    timezone_object_construct(tz, return_value, 1 TSRMLS_CC);
102}
103
104U_CFUNC PHP_FUNCTION(intltz_create_default)
105{
106    intl_error_reset(NULL TSRMLS_CC);
107
108    if (zend_parse_parameters_none() == FAILURE) {
109        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
110            "intltz_create_default: bad arguments", 0 TSRMLS_CC);
111        RETURN_NULL();
112    }
113
114    TimeZone *tz = TimeZone::createDefault();
115    timezone_object_construct(tz, return_value, 1 TSRMLS_CC);
116}
117
118U_CFUNC PHP_FUNCTION(intltz_get_gmt)
119{
120    intl_error_reset(NULL TSRMLS_CC);
121
122    if (zend_parse_parameters_none() == FAILURE) {
123        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
124            "intltz_get_gmt: bad arguments", 0 TSRMLS_CC);
125        RETURN_NULL();
126    }
127
128    timezone_object_construct(TimeZone::getGMT(), return_value, 0 TSRMLS_CC);
129}
130
131#if U_ICU_VERSION_MAJOR_NUM >= 49
132U_CFUNC PHP_FUNCTION(intltz_get_unknown)
133{
134    intl_error_reset(NULL TSRMLS_CC);
135
136    if (zend_parse_parameters_none() == FAILURE) {
137        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
138            "intltz_get_unknown: bad arguments", 0 TSRMLS_CC);
139        RETURN_NULL();
140    }
141
142    timezone_object_construct(&TimeZone::getUnknown(), return_value, 0 TSRMLS_CC);
143}
144#endif
145
146U_CFUNC PHP_FUNCTION(intltz_create_enumeration)
147{
148    zval                **arg = NULL;
149    StringEnumeration   *se   = NULL;
150    intl_error_reset(NULL TSRMLS_CC);
151
152    /* double indirection to have the zend engine destroy the new zval that
153     * results from separation */
154    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg) == FAILURE) {
155        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
156            "intltz_create_enumeration: bad arguments", 0 TSRMLS_CC);
157        RETURN_FALSE;
158    }
159
160    if (arg == NULL || Z_TYPE_PP(arg) == IS_NULL) {
161        se = TimeZone::createEnumeration();
162    } else if (Z_TYPE_PP(arg) == IS_LONG) {
163int_offset:
164        if (Z_LVAL_PP(arg) < (long)INT32_MIN ||
165                Z_LVAL_PP(arg) > (long)INT32_MAX) {
166            intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
167                "intltz_create_enumeration: value is out of range", 0 TSRMLS_CC);
168            RETURN_FALSE;
169        } else {
170            se = TimeZone::createEnumeration((int32_t) Z_LVAL_PP(arg));
171        }
172    } else if (Z_TYPE_PP(arg) == IS_DOUBLE) {
173double_offset:
174        convert_to_long_ex(arg);
175        goto int_offset;
176    } else if (Z_TYPE_PP(arg) == IS_OBJECT || Z_TYPE_PP(arg) == IS_STRING) {
177        long lval;
178        double dval;
179        convert_to_string_ex(arg);
180        switch (is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lval, &dval, 0)) {
181        case IS_DOUBLE:
182            SEPARATE_ZVAL(arg);
183            zval_dtor(*arg);
184            Z_TYPE_PP(arg) = IS_DOUBLE;
185            Z_DVAL_PP(arg) = dval;
186            goto double_offset;
187        case IS_LONG:
188            SEPARATE_ZVAL(arg);
189            zval_dtor(*arg);
190            Z_TYPE_PP(arg) = IS_LONG;
191            Z_LVAL_PP(arg) = lval;
192            goto int_offset;
193        }
194        /* else call string version */
195        se = TimeZone::createEnumeration(Z_STRVAL_PP(arg));
196    } else {
197        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
198            "intltz_create_enumeration: invalid argument type", 0 TSRMLS_CC);
199        RETURN_FALSE;
200    }
201
202    if (se) {
203        IntlIterator_from_StringEnumeration(se, return_value TSRMLS_CC);
204    } else {
205        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
206            "intltz_create_enumeration: error obtaining enumeration", 0 TSRMLS_CC);
207        RETVAL_FALSE;
208    }
209}
210
211U_CFUNC PHP_FUNCTION(intltz_count_equivalent_ids)
212{
213    char    *str_id;
214    int     str_id_len;
215    intl_error_reset(NULL TSRMLS_CC);
216
217    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
218            &str_id, &str_id_len) == FAILURE) {
219        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
220            "intltz_count_equivalent_ids: bad arguments", 0 TSRMLS_CC);
221        RETURN_FALSE;
222    }
223
224    UErrorCode status = UErrorCode();
225    UnicodeString id = UnicodeString();
226    if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) {
227        intl_error_set(NULL, status,
228            "intltz_count_equivalent_ids: could not convert time zone id to UTF-16", 0 TSRMLS_CC);
229        RETURN_FALSE;
230    }
231
232    int32_t result = TimeZone::countEquivalentIDs(id);
233    RETURN_LONG((long)result);
234}
235
236#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48
237U_CFUNC PHP_FUNCTION(intltz_create_time_zone_id_enumeration)
238{
239    long    zoneType,
240            offset_arg;
241    char    *region     = NULL;
242    int     region_len  = 0;
243    int32_t offset,
244            *offsetp    = NULL;
245    int     arg3isnull  = 0;
246    intl_error_reset(NULL TSRMLS_CC);
247
248    /* must come before zpp because zpp would convert the arg in the stack to 0 */
249    if (ZEND_NUM_ARGS() == 3) {
250        zval **dummy, **zvoffset;
251        arg3isnull = zend_get_parameters_ex(3, &dummy, &dummy, &zvoffset)
252                != FAILURE && Z_TYPE_PP(zvoffset) == IS_NULL;
253    }
254
255    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s!l",
256            &zoneType, &region, &region_len, &offset_arg) == FAILURE) {
257        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
258            "intltz_create_time_zone_id_enumeration: bad arguments", 0 TSRMLS_CC);
259        RETURN_FALSE;
260    }
261
262    if (zoneType != UCAL_ZONE_TYPE_ANY && zoneType != UCAL_ZONE_TYPE_CANONICAL
263            && zoneType != UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
264        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
265            "intltz_create_time_zone_id_enumeration: bad zone type", 0 TSRMLS_CC);
266        RETURN_FALSE;
267    }
268
269    if (ZEND_NUM_ARGS() == 3) {
270        if (offset_arg < (long)INT32_MIN || offset_arg > (long)INT32_MAX) {
271            intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
272                "intltz_create_time_zone_id_enumeration: offset out of bounds", 0 TSRMLS_CC);
273            RETURN_FALSE;
274        }
275
276        if (!arg3isnull) {
277            offset = (int32_t)offset_arg;
278            offsetp = &offset;
279        } //else leave offsetp NULL
280    }
281
282    StringEnumeration *se;
283    UErrorCode uec = UErrorCode();
284    se = TimeZone::createTimeZoneIDEnumeration((USystemTimeZoneType)zoneType,
285        region, offsetp, uec);
286    INTL_CHECK_STATUS(uec, "intltz_create_time_zone_id_enumeration: "
287        "Error obtaining time zone id enumeration")
288
289    IntlIterator_from_StringEnumeration(se, return_value TSRMLS_CC);
290}
291#endif
292
293U_CFUNC PHP_FUNCTION(intltz_get_canonical_id)
294{
295    char    *str_id;
296    int     str_id_len;
297    zval    *is_systemid = NULL;
298    intl_error_reset(NULL TSRMLS_CC);
299
300    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z",
301            &str_id, &str_id_len, &is_systemid) == FAILURE) {
302        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
303            "intltz_get_canonical_id: bad arguments", 0 TSRMLS_CC);
304        RETURN_FALSE;
305    }
306
307    UErrorCode status = UErrorCode();
308    UnicodeString id;
309    if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) {
310        intl_error_set(NULL, status,
311            "intltz_get_canonical_id: could not convert time zone id to UTF-16", 0 TSRMLS_CC);
312        RETURN_FALSE;
313    }
314
315    UnicodeString result;
316    UBool isSystemID;
317    TimeZone::getCanonicalID(id, result, isSystemID, status);
318    INTL_CHECK_STATUS(status, "intltz_get_canonical_id: error obtaining canonical ID");
319
320    intl_convert_utf16_to_utf8(&Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value),
321        result.getBuffer(), result.length(), &status);
322    INTL_CHECK_STATUS(status,
323        "intltz_get_canonical_id: could not convert time zone id to UTF-16");
324    Z_TYPE_P(return_value) = IS_STRING;
325
326    if (is_systemid) { /* by-ref argument passed */
327        zval_dtor(is_systemid);
328        ZVAL_BOOL(is_systemid, isSystemID);
329    }
330}
331
332#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48
333U_CFUNC PHP_FUNCTION(intltz_get_region)
334{
335    char    *str_id;
336    int     str_id_len;
337    char    outbuf[3];
338    intl_error_reset(NULL TSRMLS_CC);
339
340    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
341            &str_id, &str_id_len) == FAILURE) {
342        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
343            "intltz_get_region: bad arguments", 0 TSRMLS_CC);
344        RETURN_FALSE;
345    }
346
347    UErrorCode status = UErrorCode();
348    UnicodeString id;
349    if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) {
350        intl_error_set(NULL, status,
351            "intltz_get_region: could not convert time zone id to UTF-16", 0 TSRMLS_CC);
352        RETURN_FALSE;
353    }
354
355    int32_t region_len = TimeZone::getRegion(id, outbuf, sizeof(outbuf), status);
356    INTL_CHECK_STATUS(status, "intltz_get_region: Error obtaining region");
357
358    RETURN_STRINGL(outbuf, region_len, 1);
359}
360#endif
361
362U_CFUNC PHP_FUNCTION(intltz_get_tz_data_version)
363{
364    intl_error_reset(NULL TSRMLS_CC);
365
366    if (zend_parse_parameters_none() == FAILURE) {
367        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
368            "intltz_get_tz_data_version: bad arguments", 0 TSRMLS_CC);
369        RETURN_FALSE;
370    }
371
372    UErrorCode status = UErrorCode();
373    const char *res = TimeZone::getTZDataVersion(status);
374    INTL_CHECK_STATUS(status, "intltz_get_tz_data_version: "
375        "Error obtaining time zone data version");
376
377    RETURN_STRING(res, 1);
378}
379
380U_CFUNC PHP_FUNCTION(intltz_get_equivalent_id)
381{
382    char    *str_id;
383    int     str_id_len;
384    long    index;
385    intl_error_reset(NULL TSRMLS_CC);
386
387    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl",
388            &str_id, &str_id_len, &index) == FAILURE ||
389            index < (long)INT32_MIN || index > (long)INT32_MAX) {
390        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
391            "intltz_get_equivalent_id: bad arguments", 0 TSRMLS_CC);
392        RETURN_FALSE;
393    }
394
395    UErrorCode status = UErrorCode();
396    UnicodeString id;
397    if (intl_stringFromChar(id, str_id, str_id_len, &status) == FAILURE) {
398        intl_error_set(NULL, status,
399            "intltz_get_equivalent_id: could not convert time zone id to UTF-16", 0 TSRMLS_CC);
400        RETURN_FALSE;
401    }
402
403    const UnicodeString result = TimeZone::getEquivalentID(id, (int32_t)index);
404    intl_convert_utf16_to_utf8(&Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value),
405        result.getBuffer(), result.length(), &status);
406    INTL_CHECK_STATUS(status, "intltz_get_equivalent_id: "
407        "could not convert resulting time zone id to UTF-16");
408    Z_TYPE_P(return_value) = IS_STRING;
409}
410
411U_CFUNC PHP_FUNCTION(intltz_get_id)
412{
413    TIMEZONE_METHOD_INIT_VARS;
414
415    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
416            &object, TimeZone_ce_ptr) == FAILURE) {
417        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
418            "intltz_get_id: bad arguments", 0 TSRMLS_CC);
419        RETURN_FALSE;
420    }
421
422    TIMEZONE_METHOD_FETCH_OBJECT;
423
424    UnicodeString id_us;
425    to->utimezone->getID(id_us);
426
427    char *id = NULL;
428    int  id_len   = 0;
429
430    intl_convert_utf16_to_utf8(&id, &id_len,
431        id_us.getBuffer(), id_us.length(), TIMEZONE_ERROR_CODE_P(to));
432    INTL_METHOD_CHECK_STATUS(to, "intltz_get_id: Could not convert id to UTF-8");
433
434    RETURN_STRINGL(id, id_len, 0);
435}
436
437U_CFUNC PHP_FUNCTION(intltz_use_daylight_time)
438{
439    TIMEZONE_METHOD_INIT_VARS;
440
441    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
442            &object, TimeZone_ce_ptr) == FAILURE) {
443        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
444            "intltz_use_daylight_time: bad arguments", 0 TSRMLS_CC);
445        RETURN_FALSE;
446    }
447
448    TIMEZONE_METHOD_FETCH_OBJECT;
449
450    RETURN_BOOL(to->utimezone->useDaylightTime());
451}
452
453U_CFUNC PHP_FUNCTION(intltz_get_offset)
454{
455    UDate       date;
456    zend_bool   local;
457    zval        *rawOffsetArg,
458                *dstOffsetArg;
459    int32_t     rawOffset,
460                dstOffset;
461    TIMEZONE_METHOD_INIT_VARS;
462
463    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
464            "Odbzz", &object, TimeZone_ce_ptr, &date, &local, &rawOffsetArg,
465            &dstOffsetArg) == FAILURE) {
466        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
467            "intltz_get_offset: bad arguments", 0 TSRMLS_CC);
468        RETURN_FALSE;
469    }
470
471    TIMEZONE_METHOD_FETCH_OBJECT;
472
473    to->utimezone->getOffset(date, (UBool) local, rawOffset, dstOffset,
474        TIMEZONE_ERROR_CODE(to));
475
476    INTL_METHOD_CHECK_STATUS(to, "intltz_get_offset: error obtaining offset");
477
478    zval_dtor(rawOffsetArg);
479    ZVAL_LONG(rawOffsetArg, rawOffset);
480    zval_dtor(dstOffsetArg);
481    ZVAL_LONG(dstOffsetArg, dstOffset);
482
483    RETURN_TRUE;
484}
485
486U_CFUNC PHP_FUNCTION(intltz_get_raw_offset)
487{
488    TIMEZONE_METHOD_INIT_VARS;
489
490    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
491            "O", &object, TimeZone_ce_ptr) == FAILURE) {
492        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
493            "intltz_get_raw_offset: bad arguments", 0 TSRMLS_CC);
494        RETURN_FALSE;
495    }
496
497    TIMEZONE_METHOD_FETCH_OBJECT;
498
499    RETURN_LONG(to->utimezone->getRawOffset());
500}
501
502U_CFUNC PHP_FUNCTION(intltz_has_same_rules)
503{
504    zval            *other_object;
505    TimeZone_object *other_to;
506    TIMEZONE_METHOD_INIT_VARS;
507
508    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
509            "OO", &object, TimeZone_ce_ptr, &other_object, TimeZone_ce_ptr)
510            == FAILURE) {
511        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
512            "intltz_has_same_rules: bad arguments", 0 TSRMLS_CC);
513        RETURN_FALSE;
514    }
515    TIMEZONE_METHOD_FETCH_OBJECT;
516    other_to = (TimeZone_object *) zend_object_store_get_object(other_object TSRMLS_CC);
517    if (other_to->utimezone == NULL) {
518        intl_errors_set(&to->err, U_ILLEGAL_ARGUMENT_ERROR,
519            "intltz_has_same_rules: The second IntlTimeZone is unconstructed", 0 TSRMLS_CC);
520        RETURN_FALSE;
521    }
522
523    RETURN_BOOL(to->utimezone->hasSameRules(*other_to->utimezone));
524}
525
526static const TimeZone::EDisplayType display_types[] = {
527    TimeZone::SHORT,                TimeZone::LONG,
528#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
529    TimeZone::SHORT_GENERIC,        TimeZone::LONG_GENERIC,
530    TimeZone::SHORT_GMT,            TimeZone::LONG_GMT,
531    TimeZone::SHORT_COMMONLY_USED,  TimeZone::GENERIC_LOCATION
532#endif
533};
534
535U_CFUNC PHP_FUNCTION(intltz_get_display_name)
536{
537    zend_bool   daylight        = 0;
538    long        display_type    = TimeZone::LONG;
539    const char  *locale_str     = NULL;
540    int         dummy           = 0;
541    TIMEZONE_METHOD_INIT_VARS;
542
543    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
544            "O|bls!", &object, TimeZone_ce_ptr, &daylight, &display_type,
545            &locale_str, &dummy) == FAILURE) {
546        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
547            "intltz_get_display_name: bad arguments", 0 TSRMLS_CC);
548        RETURN_FALSE;
549    }
550
551    bool found = false;
552    for (int i = 0; !found && i < sizeof(display_types)/sizeof(*display_types); i++) {
553        if (display_types[i] == display_type)
554            found = true;
555    }
556    if (!found) {
557        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
558            "intltz_get_display_name: wrong display type", 0 TSRMLS_CC);
559        RETURN_FALSE;
560    }
561
562    if (!locale_str) {
563        locale_str = intl_locale_get_default(TSRMLS_C);
564    }
565
566    TIMEZONE_METHOD_FETCH_OBJECT;
567
568    UnicodeString result;
569    to->utimezone->getDisplayName((UBool)daylight, (TimeZone::EDisplayType)display_type,
570        Locale::createFromName(locale_str), result);
571
572    intl_convert_utf16_to_utf8(&Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value),
573        result.getBuffer(), result.length(), TIMEZONE_ERROR_CODE_P(to));
574    INTL_METHOD_CHECK_STATUS(to, "intltz_get_display_name: "
575        "could not convert resulting time zone id to UTF-16");
576
577    Z_TYPE_P(return_value) = IS_STRING;
578}
579
580U_CFUNC PHP_FUNCTION(intltz_get_dst_savings)
581{
582    TIMEZONE_METHOD_INIT_VARS;
583
584    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
585            "O", &object, TimeZone_ce_ptr) == FAILURE) {
586        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
587            "intltz_get_dst_savings: bad arguments", 0 TSRMLS_CC);
588        RETURN_FALSE;
589    }
590
591    TIMEZONE_METHOD_FETCH_OBJECT;
592
593    RETURN_LONG((long)to->utimezone->getDSTSavings());
594}
595
596U_CFUNC PHP_FUNCTION(intltz_to_date_time_zone)
597{
598    TIMEZONE_METHOD_INIT_VARS;
599
600    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
601            "O", &object, TimeZone_ce_ptr) == FAILURE) {
602        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
603            "intltz_to_date_time_zone: bad arguments", 0 TSRMLS_CC);
604        RETURN_FALSE;
605    }
606
607    TIMEZONE_METHOD_FETCH_OBJECT;
608
609    zval *ret = timezone_convert_to_datetimezone(to->utimezone,
610        &TIMEZONE_ERROR(to), "intltz_to_date_time_zone" TSRMLS_CC);
611
612    if (ret) {
613        RETURN_ZVAL(ret, 1, 1);
614    } else {
615        RETURN_FALSE;
616    }
617}
618
619U_CFUNC PHP_FUNCTION(intltz_get_error_code)
620{
621    TIMEZONE_METHOD_INIT_VARS
622
623    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
624            &object, TimeZone_ce_ptr) == FAILURE) {
625        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
626            "intltz_get_error_code: bad arguments", 0 TSRMLS_CC);
627        RETURN_FALSE;
628    }
629
630    /* Fetch the object (without resetting its last error code ). */
631    to = (TimeZone_object*)zend_object_store_get_object(object TSRMLS_CC);
632    if (to == NULL)
633        RETURN_FALSE;
634
635    RETURN_LONG((long)TIMEZONE_ERROR_CODE(to));
636}
637
638U_CFUNC PHP_FUNCTION(intltz_get_error_message)
639{
640    const char* message = NULL;
641    TIMEZONE_METHOD_INIT_VARS
642
643    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
644            &object, TimeZone_ce_ptr) == FAILURE) {
645        intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
646            "intltz_get_error_message: bad arguments", 0 TSRMLS_CC );
647        RETURN_FALSE;
648    }
649
650
651    /* Fetch the object (without resetting its last error code ). */
652    to = (TimeZone_object*)zend_object_store_get_object(object TSRMLS_CC);
653    if (to == NULL)
654        RETURN_FALSE;
655
656    /* Return last error message. */
657    message = intl_error_get_message(TIMEZONE_ERROR_P(to) TSRMLS_CC);
658    RETURN_STRING(message, 0);
659}
660