Return to php_date.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / date |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 The PHP Group | ! 6: +----------------------------------------------------------------------+ ! 7: | This source file is subject to version 3.01 of the PHP license, | ! 8: | that is bundled with this package in the file LICENSE, and is | ! 9: | available through the world-wide-web at the following url: | ! 10: | http://www.php.net/license/3_01.txt | ! 11: | If you did not receive a copy of the PHP license and are unable to | ! 12: | obtain it through the world-wide-web, please send a note to | ! 13: | license@php.net so we can mail you a copy immediately. | ! 14: +----------------------------------------------------------------------+ ! 15: | Authors: Derick Rethans <derick@derickrethans.nl> | ! 16: +----------------------------------------------------------------------+ ! 17: */ ! 18: ! 19: /* $Id: php_date.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 20: ! 21: #include "php.h" ! 22: #include "php_streams.h" ! 23: #include "php_main.h" ! 24: #include "php_globals.h" ! 25: #include "php_ini.h" ! 26: #include "ext/standard/info.h" ! 27: #include "ext/standard/php_versioning.h" ! 28: #include "ext/standard/php_math.h" ! 29: #include "php_date.h" ! 30: #include "zend_interfaces.h" ! 31: #include "lib/timelib.h" ! 32: #include <time.h> ! 33: ! 34: #ifdef PHP_WIN32 ! 35: static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; } ! 36: #elif defined(__GNUC__) && __GNUC__ < 3 ! 37: static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i; } ! 38: #else ! 39: static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; } ! 40: #endif ! 41: ! 42: /* {{{ arginfo */ ! 43: ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1) ! 44: ZEND_ARG_INFO(0, format) ! 45: ZEND_ARG_INFO(0, timestamp) ! 46: ZEND_END_ARG_INFO() ! 47: ! 48: ZEND_BEGIN_ARG_INFO_EX(arginfo_gmdate, 0, 0, 1) ! 49: ZEND_ARG_INFO(0, format) ! 50: ZEND_ARG_INFO(0, timestamp) ! 51: ZEND_END_ARG_INFO() ! 52: ! 53: ZEND_BEGIN_ARG_INFO_EX(arginfo_idate, 0, 0, 1) ! 54: ZEND_ARG_INFO(0, format) ! 55: ZEND_ARG_INFO(0, timestamp) ! 56: ZEND_END_ARG_INFO() ! 57: ! 58: ZEND_BEGIN_ARG_INFO_EX(arginfo_strtotime, 0, 0, 1) ! 59: ZEND_ARG_INFO(0, time) ! 60: ZEND_ARG_INFO(0, now) ! 61: ZEND_END_ARG_INFO() ! 62: ! 63: ZEND_BEGIN_ARG_INFO_EX(arginfo_mktime, 0, 0, 0) ! 64: ZEND_ARG_INFO(0, hour) ! 65: ZEND_ARG_INFO(0, min) ! 66: ZEND_ARG_INFO(0, sec) ! 67: ZEND_ARG_INFO(0, mon) ! 68: ZEND_ARG_INFO(0, day) ! 69: ZEND_ARG_INFO(0, year) ! 70: ZEND_END_ARG_INFO() ! 71: ! 72: ZEND_BEGIN_ARG_INFO_EX(arginfo_gmmktime, 0, 0, 0) ! 73: ZEND_ARG_INFO(0, hour) ! 74: ZEND_ARG_INFO(0, min) ! 75: ZEND_ARG_INFO(0, sec) ! 76: ZEND_ARG_INFO(0, mon) ! 77: ZEND_ARG_INFO(0, day) ! 78: ZEND_ARG_INFO(0, year) ! 79: ZEND_END_ARG_INFO() ! 80: ! 81: ZEND_BEGIN_ARG_INFO(arginfo_checkdate, 0) ! 82: ZEND_ARG_INFO(0, month) ! 83: ZEND_ARG_INFO(0, day) ! 84: ZEND_ARG_INFO(0, year) ! 85: ZEND_END_ARG_INFO() ! 86: ! 87: ZEND_BEGIN_ARG_INFO_EX(arginfo_strftime, 0, 0, 1) ! 88: ZEND_ARG_INFO(0, format) ! 89: ZEND_ARG_INFO(0, timestamp) ! 90: ZEND_END_ARG_INFO() ! 91: ! 92: ZEND_BEGIN_ARG_INFO_EX(arginfo_gmstrftime, 0, 0, 1) ! 93: ZEND_ARG_INFO(0, format) ! 94: ZEND_ARG_INFO(0, timestamp) ! 95: ZEND_END_ARG_INFO() ! 96: ! 97: ZEND_BEGIN_ARG_INFO(arginfo_time, 0) ! 98: ZEND_END_ARG_INFO() ! 99: ! 100: ZEND_BEGIN_ARG_INFO_EX(arginfo_localtime, 0, 0, 0) ! 101: ZEND_ARG_INFO(0, timestamp) ! 102: ZEND_ARG_INFO(0, associative_array) ! 103: ZEND_END_ARG_INFO() ! 104: ! 105: ZEND_BEGIN_ARG_INFO_EX(arginfo_getdate, 0, 0, 0) ! 106: ZEND_ARG_INFO(0, timestamp) ! 107: ZEND_END_ARG_INFO() ! 108: ! 109: ZEND_BEGIN_ARG_INFO(arginfo_date_default_timezone_set, 0) ! 110: ZEND_ARG_INFO(0, timezone_identifier) ! 111: ZEND_END_ARG_INFO() ! 112: ! 113: ZEND_BEGIN_ARG_INFO(arginfo_date_default_timezone_get, 0) ! 114: ZEND_END_ARG_INFO() ! 115: ! 116: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sunrise, 0, 0, 1) ! 117: ZEND_ARG_INFO(0, time) ! 118: ZEND_ARG_INFO(0, format) ! 119: ZEND_ARG_INFO(0, latitude) ! 120: ZEND_ARG_INFO(0, longitude) ! 121: ZEND_ARG_INFO(0, zenith) ! 122: ZEND_ARG_INFO(0, gmt_offset) ! 123: ZEND_END_ARG_INFO() ! 124: ! 125: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sunset, 0, 0, 1) ! 126: ZEND_ARG_INFO(0, time) ! 127: ZEND_ARG_INFO(0, format) ! 128: ZEND_ARG_INFO(0, latitude) ! 129: ZEND_ARG_INFO(0, longitude) ! 130: ZEND_ARG_INFO(0, zenith) ! 131: ZEND_ARG_INFO(0, gmt_offset) ! 132: ZEND_END_ARG_INFO() ! 133: ! 134: ZEND_BEGIN_ARG_INFO(arginfo_date_sun_info, 0) ! 135: ZEND_ARG_INFO(0, time) ! 136: ZEND_ARG_INFO(0, latitude) ! 137: ZEND_ARG_INFO(0, longitude) ! 138: ZEND_END_ARG_INFO() ! 139: ! 140: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_create, 0, 0, 0) ! 141: ZEND_ARG_INFO(0, time) ! 142: ZEND_ARG_INFO(0, object) ! 143: ZEND_END_ARG_INFO() ! 144: ! 145: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_create_from_format, 0, 0, 2) ! 146: ZEND_ARG_INFO(0, format) ! 147: ZEND_ARG_INFO(0, time) ! 148: ZEND_ARG_INFO(0, object) ! 149: ZEND_END_ARG_INFO() ! 150: ! 151: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_parse, 0, 0, 1) ! 152: ZEND_ARG_INFO(0, date) ! 153: ZEND_END_ARG_INFO() ! 154: ! 155: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_parse_from_format, 0, 0, 2) ! 156: ZEND_ARG_INFO(0, format) ! 157: ZEND_ARG_INFO(0, date) ! 158: ZEND_END_ARG_INFO() ! 159: ! 160: ZEND_BEGIN_ARG_INFO(arginfo_date_get_last_errors, 0) ! 161: ZEND_END_ARG_INFO() ! 162: ! 163: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_format, 0, 0, 2) ! 164: ZEND_ARG_INFO(0, object) ! 165: ZEND_ARG_INFO(0, format) ! 166: ZEND_END_ARG_INFO() ! 167: ! 168: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_format, 0, 0, 1) ! 169: ZEND_ARG_INFO(0, format) ! 170: ZEND_END_ARG_INFO() ! 171: ! 172: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_modify, 0, 0, 2) ! 173: ZEND_ARG_INFO(0, object) ! 174: ZEND_ARG_INFO(0, modify) ! 175: ZEND_END_ARG_INFO() ! 176: ! 177: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_modify, 0, 0, 1) ! 178: ZEND_ARG_INFO(0, modify) ! 179: ZEND_END_ARG_INFO() ! 180: ! 181: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_add, 0, 0, 2) ! 182: ZEND_ARG_INFO(0, object) ! 183: ZEND_ARG_INFO(0, interval) ! 184: ZEND_END_ARG_INFO() ! 185: ! 186: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_add, 0, 0, 1) ! 187: ZEND_ARG_INFO(0, interval) ! 188: ZEND_END_ARG_INFO() ! 189: ! 190: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_sub, 0, 0, 2) ! 191: ZEND_ARG_INFO(0, object) ! 192: ZEND_ARG_INFO(0, interval) ! 193: ZEND_END_ARG_INFO() ! 194: ! 195: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_sub, 0, 0, 1) ! 196: ZEND_ARG_INFO(0, interval) ! 197: ZEND_END_ARG_INFO() ! 198: ! 199: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_get, 0, 0, 1) ! 200: ZEND_ARG_INFO(0, object) ! 201: ZEND_END_ARG_INFO() ! 202: ! 203: ZEND_BEGIN_ARG_INFO(arginfo_date_method_timezone_get, 0) ! 204: ZEND_END_ARG_INFO() ! 205: ! 206: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timezone_set, 0, 0, 2) ! 207: ZEND_ARG_INFO(0, object) ! 208: ZEND_ARG_INFO(0, timezone) ! 209: ZEND_END_ARG_INFO() ! 210: ! 211: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_timezone_set, 0, 0, 1) ! 212: ZEND_ARG_INFO(0, timezone) ! 213: ZEND_END_ARG_INFO() ! 214: ! 215: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_offset_get, 0, 0, 1) ! 216: ZEND_ARG_INFO(0, object) ! 217: ZEND_END_ARG_INFO() ! 218: ! 219: ZEND_BEGIN_ARG_INFO(arginfo_date_method_offset_get, 0) ! 220: ZEND_END_ARG_INFO() ! 221: ! 222: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_diff, 0, 0, 2) ! 223: ZEND_ARG_INFO(0, object) ! 224: ZEND_ARG_INFO(0, object2) ! 225: ZEND_ARG_INFO(0, absolute) ! 226: ZEND_END_ARG_INFO() ! 227: ! 228: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_diff, 0, 0, 1) ! 229: ZEND_ARG_INFO(0, object) ! 230: ZEND_ARG_INFO(0, absolute) ! 231: ZEND_END_ARG_INFO() ! 232: ! 233: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_time_set, 0, 0, 3) ! 234: ZEND_ARG_INFO(0, object) ! 235: ZEND_ARG_INFO(0, hour) ! 236: ZEND_ARG_INFO(0, minute) ! 237: ZEND_ARG_INFO(0, second) ! 238: ZEND_END_ARG_INFO() ! 239: ! 240: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_time_set, 0, 0, 2) ! 241: ZEND_ARG_INFO(0, hour) ! 242: ZEND_ARG_INFO(0, minute) ! 243: ZEND_ARG_INFO(0, second) ! 244: ZEND_END_ARG_INFO() ! 245: ! 246: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_date_set, 0, 0, 4) ! 247: ZEND_ARG_INFO(0, object) ! 248: ZEND_ARG_INFO(0, year) ! 249: ZEND_ARG_INFO(0, month) ! 250: ZEND_ARG_INFO(0, day) ! 251: ZEND_END_ARG_INFO() ! 252: ! 253: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_date_set, 0, 0, 3) ! 254: ZEND_ARG_INFO(0, year) ! 255: ZEND_ARG_INFO(0, month) ! 256: ZEND_ARG_INFO(0, day) ! 257: ZEND_END_ARG_INFO() ! 258: ! 259: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_isodate_set, 0, 0, 3) ! 260: ZEND_ARG_INFO(0, object) ! 261: ZEND_ARG_INFO(0, year) ! 262: ZEND_ARG_INFO(0, week) ! 263: ZEND_ARG_INFO(0, day) ! 264: ZEND_END_ARG_INFO() ! 265: ! 266: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_isodate_set, 0, 0, 2) ! 267: ZEND_ARG_INFO(0, year) ! 268: ZEND_ARG_INFO(0, week) ! 269: ZEND_ARG_INFO(0, day) ! 270: ZEND_END_ARG_INFO() ! 271: ! 272: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timestamp_set, 0, 0, 2) ! 273: ZEND_ARG_INFO(0, object) ! 274: ZEND_ARG_INFO(0, unixtimestamp) ! 275: ZEND_END_ARG_INFO() ! 276: ! 277: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_method_timestamp_set, 0, 0, 1) ! 278: ZEND_ARG_INFO(0, unixtimestamp) ! 279: ZEND_END_ARG_INFO() ! 280: ! 281: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_timestamp_get, 0, 0, 1) ! 282: ZEND_ARG_INFO(0, object) ! 283: ZEND_END_ARG_INFO() ! 284: ! 285: ZEND_BEGIN_ARG_INFO(arginfo_date_method_timestamp_get, 0) ! 286: ZEND_END_ARG_INFO() ! 287: ! 288: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_open, 0, 0, 1) ! 289: ZEND_ARG_INFO(0, timezone) ! 290: ZEND_END_ARG_INFO() ! 291: ! 292: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_get, 0, 0, 1) ! 293: ZEND_ARG_INFO(0, object) ! 294: ZEND_END_ARG_INFO() ! 295: ! 296: ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_name_get, 0) ! 297: ZEND_END_ARG_INFO() ! 298: ! 299: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_name_from_abbr, 0, 0, 1) ! 300: ZEND_ARG_INFO(0, abbr) ! 301: ZEND_ARG_INFO(0, gmtoffset) ! 302: ZEND_ARG_INFO(0, isdst) ! 303: ZEND_END_ARG_INFO() ! 304: ! 305: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_offset_get, 0, 0, 2) ! 306: ZEND_ARG_INFO(0, object) ! 307: ZEND_ARG_INFO(0, datetime) ! 308: ZEND_END_ARG_INFO() ! 309: ! 310: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_method_offset_get, 0, 0, 1) ! 311: ZEND_ARG_INFO(0, datetime) ! 312: ZEND_END_ARG_INFO() ! 313: ! 314: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_transitions_get, 0, 0, 1) ! 315: ZEND_ARG_INFO(0, object) ! 316: ZEND_ARG_INFO(0, timestamp_begin) ! 317: ZEND_ARG_INFO(0, timestamp_end) ! 318: ZEND_END_ARG_INFO() ! 319: ! 320: ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_transitions_get, 0) ! 321: ZEND_ARG_INFO(0, timestamp_begin) ! 322: ZEND_ARG_INFO(0, timestamp_end) ! 323: ZEND_END_ARG_INFO() ! 324: ! 325: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_location_get, 0, 0, 1) ! 326: ZEND_ARG_INFO(0, object) ! 327: ZEND_END_ARG_INFO() ! 328: ! 329: ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_location_get, 0) ! 330: ZEND_END_ARG_INFO() ! 331: ! 332: ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_identifiers_list, 0, 0, 0) ! 333: ZEND_ARG_INFO(0, what) ! 334: ZEND_ARG_INFO(0, country) ! 335: ZEND_END_ARG_INFO() ! 336: ! 337: ZEND_BEGIN_ARG_INFO(arginfo_timezone_abbreviations_list, 0) ! 338: ZEND_END_ARG_INFO() ! 339: ! 340: ZEND_BEGIN_ARG_INFO(arginfo_timezone_version_get, 0) ! 341: ZEND_END_ARG_INFO() ! 342: ! 343: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_create_from_date_string, 0, 0, 1) ! 344: ZEND_ARG_INFO(0, time) ! 345: ZEND_END_ARG_INFO() ! 346: ! 347: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_format, 0, 0, 2) ! 348: ZEND_ARG_INFO(0, object) ! 349: ZEND_ARG_INFO(0, format) ! 350: ZEND_END_ARG_INFO() ! 351: ! 352: ZEND_BEGIN_ARG_INFO(arginfo_date_method_interval_format, 0) ! 353: ZEND_ARG_INFO(0, format) ! 354: ZEND_END_ARG_INFO() ! 355: ! 356: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_period_construct, 0, 0, 3) ! 357: ZEND_ARG_INFO(0, start) ! 358: ZEND_ARG_INFO(0, interval) ! 359: ZEND_ARG_INFO(0, end) ! 360: ZEND_END_ARG_INFO() ! 361: ! 362: ZEND_BEGIN_ARG_INFO_EX(arginfo_date_interval_construct, 0, 0, 0) ! 363: ZEND_ARG_INFO(0, interval_spec) ! 364: ZEND_END_ARG_INFO() ! 365: /* }}} */ ! 366: ! 367: /* {{{ Function table */ ! 368: const zend_function_entry date_functions[] = { ! 369: PHP_FE(strtotime, arginfo_strtotime) ! 370: PHP_FE(date, arginfo_date) ! 371: PHP_FE(idate, arginfo_idate) ! 372: PHP_FE(gmdate, arginfo_gmdate) ! 373: PHP_FE(mktime, arginfo_mktime) ! 374: PHP_FE(gmmktime, arginfo_gmmktime) ! 375: PHP_FE(checkdate, arginfo_checkdate) ! 376: ! 377: #ifdef HAVE_STRFTIME ! 378: PHP_FE(strftime, arginfo_strftime) ! 379: PHP_FE(gmstrftime, arginfo_gmstrftime) ! 380: #endif ! 381: ! 382: PHP_FE(time, arginfo_time) ! 383: PHP_FE(localtime, arginfo_localtime) ! 384: PHP_FE(getdate, arginfo_getdate) ! 385: ! 386: /* Advanced Interface */ ! 387: PHP_FE(date_create, arginfo_date_create) ! 388: PHP_FE(date_create_from_format, arginfo_date_create_from_format) ! 389: PHP_FE(date_parse, arginfo_date_parse) ! 390: PHP_FE(date_parse_from_format, arginfo_date_parse_from_format) ! 391: PHP_FE(date_get_last_errors, arginfo_date_get_last_errors) ! 392: PHP_FE(date_format, arginfo_date_format) ! 393: PHP_FE(date_modify, arginfo_date_modify) ! 394: PHP_FE(date_add, arginfo_date_add) ! 395: PHP_FE(date_sub, arginfo_date_sub) ! 396: PHP_FE(date_timezone_get, arginfo_date_timezone_get) ! 397: PHP_FE(date_timezone_set, arginfo_date_timezone_set) ! 398: PHP_FE(date_offset_get, arginfo_date_offset_get) ! 399: PHP_FE(date_diff, arginfo_date_diff) ! 400: ! 401: PHP_FE(date_time_set, arginfo_date_time_set) ! 402: PHP_FE(date_date_set, arginfo_date_date_set) ! 403: PHP_FE(date_isodate_set, arginfo_date_isodate_set) ! 404: PHP_FE(date_timestamp_set, arginfo_date_timestamp_set) ! 405: PHP_FE(date_timestamp_get, arginfo_date_timestamp_get) ! 406: ! 407: PHP_FE(timezone_open, arginfo_timezone_open) ! 408: PHP_FE(timezone_name_get, arginfo_timezone_name_get) ! 409: PHP_FE(timezone_name_from_abbr, arginfo_timezone_name_from_abbr) ! 410: PHP_FE(timezone_offset_get, arginfo_timezone_offset_get) ! 411: PHP_FE(timezone_transitions_get, arginfo_timezone_transitions_get) ! 412: PHP_FE(timezone_location_get, arginfo_timezone_location_get) ! 413: PHP_FE(timezone_identifiers_list, arginfo_timezone_identifiers_list) ! 414: PHP_FE(timezone_abbreviations_list, arginfo_timezone_abbreviations_list) ! 415: PHP_FE(timezone_version_get, arginfo_timezone_version_get) ! 416: ! 417: PHP_FE(date_interval_create_from_date_string, arginfo_date_interval_create_from_date_string) ! 418: PHP_FE(date_interval_format, arginfo_date_interval_format) ! 419: ! 420: /* Options and Configuration */ ! 421: PHP_FE(date_default_timezone_set, arginfo_date_default_timezone_set) ! 422: PHP_FE(date_default_timezone_get, arginfo_date_default_timezone_get) ! 423: ! 424: /* Astronomical functions */ ! 425: PHP_FE(date_sunrise, arginfo_date_sunrise) ! 426: PHP_FE(date_sunset, arginfo_date_sunset) ! 427: PHP_FE(date_sun_info, arginfo_date_sun_info) ! 428: PHP_FE_END ! 429: }; ! 430: ! 431: const zend_function_entry date_funcs_date[] = { ! 432: PHP_ME(DateTime, __construct, arginfo_date_create, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) ! 433: PHP_ME(DateTime, __wakeup, NULL, ZEND_ACC_PUBLIC) ! 434: PHP_ME(DateTime, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 435: PHP_ME_MAPPING(createFromFormat, date_create_from_format, arginfo_date_create_from_format, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 436: PHP_ME_MAPPING(getLastErrors, date_get_last_errors, arginfo_date_get_last_errors, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 437: PHP_ME_MAPPING(format, date_format, arginfo_date_method_format, 0) ! 438: PHP_ME_MAPPING(modify, date_modify, arginfo_date_method_modify, 0) ! 439: PHP_ME_MAPPING(add, date_add, arginfo_date_method_add, 0) ! 440: PHP_ME_MAPPING(sub, date_sub, arginfo_date_method_sub, 0) ! 441: PHP_ME_MAPPING(getTimezone, date_timezone_get, arginfo_date_method_timezone_get, 0) ! 442: PHP_ME_MAPPING(setTimezone, date_timezone_set, arginfo_date_method_timezone_set, 0) ! 443: PHP_ME_MAPPING(getOffset, date_offset_get, arginfo_date_method_offset_get, 0) ! 444: PHP_ME_MAPPING(setTime, date_time_set, arginfo_date_method_time_set, 0) ! 445: PHP_ME_MAPPING(setDate, date_date_set, arginfo_date_method_date_set, 0) ! 446: PHP_ME_MAPPING(setISODate, date_isodate_set, arginfo_date_method_isodate_set, 0) ! 447: PHP_ME_MAPPING(setTimestamp, date_timestamp_set, arginfo_date_method_timestamp_set, 0) ! 448: PHP_ME_MAPPING(getTimestamp, date_timestamp_get, arginfo_date_method_timestamp_get, 0) ! 449: PHP_ME_MAPPING(diff, date_diff, arginfo_date_method_diff, 0) ! 450: PHP_FE_END ! 451: }; ! 452: ! 453: const zend_function_entry date_funcs_timezone[] = { ! 454: PHP_ME(DateTimeZone, __construct, arginfo_timezone_open, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) ! 455: PHP_ME_MAPPING(getName, timezone_name_get, arginfo_timezone_method_name_get, 0) ! 456: PHP_ME_MAPPING(getOffset, timezone_offset_get, arginfo_timezone_method_offset_get, 0) ! 457: PHP_ME_MAPPING(getTransitions, timezone_transitions_get, arginfo_timezone_method_transitions_get, 0) ! 458: PHP_ME_MAPPING(getLocation, timezone_location_get, arginfo_timezone_method_location_get, 0) ! 459: PHP_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_timezone_abbreviations_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 460: PHP_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_timezone_identifiers_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 461: PHP_FE_END ! 462: }; ! 463: ! 464: const zend_function_entry date_funcs_interval[] = { ! 465: PHP_ME(DateInterval, __construct, arginfo_date_interval_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) ! 466: PHP_ME(DateInterval, __wakeup, NULL, ZEND_ACC_PUBLIC) ! 467: PHP_ME(DateInterval, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 468: PHP_ME_MAPPING(format, date_interval_format, arginfo_date_method_interval_format, 0) ! 469: PHP_ME_MAPPING(createFromDateString, date_interval_create_from_date_string, arginfo_date_interval_create_from_date_string, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) ! 470: PHP_FE_END ! 471: }; ! 472: ! 473: const zend_function_entry date_funcs_period[] = { ! 474: PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) ! 475: PHP_FE_END ! 476: }; ! 477: ! 478: static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC); ! 479: static void date_register_classes(TSRMLS_D); ! 480: /* }}} */ ! 481: ! 482: ZEND_DECLARE_MODULE_GLOBALS(date) ! 483: static PHP_GINIT_FUNCTION(date); ! 484: ! 485: /* True global */ ! 486: timelib_tzdb *php_date_global_timezone_db; ! 487: int php_date_global_timezone_db_enabled; ! 488: ! 489: #define DATE_DEFAULT_LATITUDE "31.7667" ! 490: #define DATE_DEFAULT_LONGITUDE "35.2333" ! 491: ! 492: /* on 90'35; common sunset declaration (start of sun body appear) */ ! 493: #define DATE_SUNSET_ZENITH "90.583333" ! 494: ! 495: /* on 90'35; common sunrise declaration (sun body disappeared) */ ! 496: #define DATE_SUNRISE_ZENITH "90.583333" ! 497: ! 498: /* {{{ INI Settings */ ! 499: PHP_INI_BEGIN() ! 500: STD_PHP_INI_ENTRY("date.timezone", "", PHP_INI_ALL, OnUpdateString, default_timezone, zend_date_globals, date_globals) ! 501: PHP_INI_ENTRY("date.default_latitude", DATE_DEFAULT_LATITUDE, PHP_INI_ALL, NULL) ! 502: PHP_INI_ENTRY("date.default_longitude", DATE_DEFAULT_LONGITUDE, PHP_INI_ALL, NULL) ! 503: PHP_INI_ENTRY("date.sunset_zenith", DATE_SUNSET_ZENITH, PHP_INI_ALL, NULL) ! 504: PHP_INI_ENTRY("date.sunrise_zenith", DATE_SUNRISE_ZENITH, PHP_INI_ALL, NULL) ! 505: PHP_INI_END() ! 506: /* }}} */ ! 507: ! 508: zend_class_entry *date_ce_date, *date_ce_timezone, *date_ce_interval, *date_ce_period; ! 509: ! 510: ! 511: PHPAPI zend_class_entry *php_date_get_date_ce(void) ! 512: { ! 513: return date_ce_date; ! 514: } ! 515: ! 516: PHPAPI zend_class_entry *php_date_get_timezone_ce(void) ! 517: { ! 518: return date_ce_timezone; ! 519: } ! 520: ! 521: static zend_object_handlers date_object_handlers_date; ! 522: static zend_object_handlers date_object_handlers_timezone; ! 523: static zend_object_handlers date_object_handlers_interval; ! 524: static zend_object_handlers date_object_handlers_period; ! 525: ! 526: #define DATE_SET_CONTEXT \ ! 527: zval *object; \ ! 528: object = getThis(); \ ! 529: ! 530: #define DATE_FETCH_OBJECT \ ! 531: php_date_obj *obj; \ ! 532: DATE_SET_CONTEXT; \ ! 533: if (object) { \ ! 534: if (zend_parse_parameters_none() == FAILURE) { \ ! 535: return; \ ! 536: } \ ! 537: } else { \ ! 538: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, NULL, "O", &object, date_ce_date) == FAILURE) { \ ! 539: RETURN_FALSE; \ ! 540: } \ ! 541: } \ ! 542: obj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); \ ! 543: ! 544: #define DATE_CHECK_INITIALIZED(member, class_name) \ ! 545: if (!(member)) { \ ! 546: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The " #class_name " object has not been correctly initialized by its constructor"); \ ! 547: RETURN_FALSE; \ ! 548: } ! 549: ! 550: static void date_object_free_storage_date(void *object TSRMLS_DC); ! 551: static void date_object_free_storage_timezone(void *object TSRMLS_DC); ! 552: static void date_object_free_storage_interval(void *object TSRMLS_DC); ! 553: static void date_object_free_storage_period(void *object TSRMLS_DC); ! 554: ! 555: static zend_object_value date_object_new_date(zend_class_entry *class_type TSRMLS_DC); ! 556: static zend_object_value date_object_new_timezone(zend_class_entry *class_type TSRMLS_DC); ! 557: static zend_object_value date_object_new_interval(zend_class_entry *class_type TSRMLS_DC); ! 558: static zend_object_value date_object_new_period(zend_class_entry *class_type TSRMLS_DC); ! 559: ! 560: static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC); ! 561: static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC); ! 562: static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC); ! 563: static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC); ! 564: ! 565: static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC); ! 566: static HashTable *date_object_get_properties(zval *object TSRMLS_DC); ! 567: static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC); ! 568: ! 569: zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC); ! 570: void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC); ! 571: ! 572: /* {{{ Module struct */ ! 573: zend_module_entry date_module_entry = { ! 574: STANDARD_MODULE_HEADER_EX, ! 575: NULL, ! 576: NULL, ! 577: "date", /* extension name */ ! 578: date_functions, /* function list */ ! 579: PHP_MINIT(date), /* process startup */ ! 580: PHP_MSHUTDOWN(date), /* process shutdown */ ! 581: PHP_RINIT(date), /* request startup */ ! 582: PHP_RSHUTDOWN(date), /* request shutdown */ ! 583: PHP_MINFO(date), /* extension info */ ! 584: PHP_VERSION, /* extension version */ ! 585: PHP_MODULE_GLOBALS(date), /* globals descriptor */ ! 586: PHP_GINIT(date), /* globals ctor */ ! 587: NULL, /* globals dtor */ ! 588: NULL, /* post deactivate */ ! 589: STANDARD_MODULE_PROPERTIES_EX ! 590: }; ! 591: /* }}} */ ! 592: ! 593: ! 594: /* {{{ PHP_GINIT_FUNCTION */ ! 595: static PHP_GINIT_FUNCTION(date) ! 596: { ! 597: date_globals->default_timezone = NULL; ! 598: date_globals->timezone = NULL; ! 599: date_globals->tzcache = NULL; ! 600: } ! 601: /* }}} */ ! 602: ! 603: ! 604: static void _php_date_tzinfo_dtor(void *tzinfo) ! 605: { ! 606: timelib_tzinfo **tzi = (timelib_tzinfo **)tzinfo; ! 607: ! 608: timelib_tzinfo_dtor(*tzi); ! 609: } ! 610: ! 611: /* {{{ PHP_RINIT_FUNCTION */ ! 612: PHP_RINIT_FUNCTION(date) ! 613: { ! 614: if (DATEG(timezone)) { ! 615: efree(DATEG(timezone)); ! 616: } ! 617: DATEG(timezone) = NULL; ! 618: DATEG(tzcache) = NULL; ! 619: DATEG(last_errors) = NULL; ! 620: ! 621: return SUCCESS; ! 622: } ! 623: /* }}} */ ! 624: ! 625: /* {{{ PHP_RSHUTDOWN_FUNCTION */ ! 626: PHP_RSHUTDOWN_FUNCTION(date) ! 627: { ! 628: if (DATEG(timezone)) { ! 629: efree(DATEG(timezone)); ! 630: } ! 631: DATEG(timezone) = NULL; ! 632: if(DATEG(tzcache)) { ! 633: zend_hash_destroy(DATEG(tzcache)); ! 634: FREE_HASHTABLE(DATEG(tzcache)); ! 635: DATEG(tzcache) = NULL; ! 636: } ! 637: if (DATEG(last_errors)) { ! 638: timelib_error_container_dtor(DATEG(last_errors)); ! 639: DATEG(last_errors) = NULL; ! 640: } ! 641: ! 642: return SUCCESS; ! 643: } ! 644: /* }}} */ ! 645: ! 646: #define DATE_TIMEZONEDB php_date_global_timezone_db ? php_date_global_timezone_db : timelib_builtin_db() ! 647: ! 648: /* ! 649: * RFC822, Section 5.1: http://www.ietf.org/rfc/rfc822.txt ! 650: * date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz ! 651: * day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" ! 652: * date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82 ! 653: * month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" ! 654: * time = hour zone ; ANSI and Military ! 655: * hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59 ! 656: * zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" / "MST" / "MDT" / "PST" / "PDT" / 1ALPHA / ( ("+" / "-") 4DIGIT ) ! 657: */ ! 658: #define DATE_FORMAT_RFC822 "D, d M y H:i:s O" ! 659: ! 660: /* ! 661: * RFC850, Section 2.1.4: http://www.ietf.org/rfc/rfc850.txt ! 662: * Format must be acceptable both to the ARPANET and to the getdate routine. ! 663: * One format that is acceptable to both is Weekday, DD-Mon-YY HH:MM:SS TIMEZONE ! 664: * TIMEZONE can be any timezone name (3 or more letters) ! 665: */ ! 666: #define DATE_FORMAT_RFC850 "l, d-M-y H:i:s T" ! 667: ! 668: /* ! 669: * RFC1036, Section 2.1.2: http://www.ietf.org/rfc/rfc1036.txt ! 670: * Its format must be acceptable both in RFC-822 and to the getdate(3) ! 671: * Wdy, DD Mon YY HH:MM:SS TIMEZONE ! 672: * There is no hope of having a complete list of timezones. Universal ! 673: * Time (GMT), the North American timezones (PST, PDT, MST, MDT, CST, ! 674: * CDT, EST, EDT) and the +/-hhmm offset specifed in RFC-822 should be supported. ! 675: */ ! 676: #define DATE_FORMAT_RFC1036 "D, d M y H:i:s O" ! 677: ! 678: /* ! 679: * RFC1123, Section 5.2.14: http://www.ietf.org/rfc/rfc1123.txt ! 680: * RFC-822 Date and Time Specification: RFC-822 Section 5 ! 681: * The syntax for the date is hereby changed to: date = 1*2DIGIT month 2*4DIGIT ! 682: */ ! 683: #define DATE_FORMAT_RFC1123 "D, d M Y H:i:s O" ! 684: ! 685: /* ! 686: * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt ! 687: * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space ! 688: * CFWS = *([FWS] comment) (([FWS] comment) / FWS) ! 689: * ! 690: * date-time = [ day-of-week "," ] date FWS time [CFWS] ! 691: * day-of-week = ([FWS] day-name) ! 692: * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" ! 693: * date = day month year ! 694: * year = 4*DIGIT ! 695: * month = (FWS month-name FWS) ! 696: * month-name = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" ! 697: * day = ([FWS] 1*2DIGIT) ! 698: * time = time-of-day FWS zone ! 699: * time-of-day = hour ":" minute [ ":" second ] ! 700: * hour = 2DIGIT ! 701: * minute = 2DIGIT ! 702: * second = 2DIGIT ! 703: * zone = (( "+" / "-" ) 4DIGIT) ! 704: */ ! 705: #define DATE_FORMAT_RFC2822 "D, d M Y H:i:s O" ! 706: /* ! 707: * RFC3339, Section 5.6: http://www.ietf.org/rfc/rfc3339.txt ! 708: * date-fullyear = 4DIGIT ! 709: * date-month = 2DIGIT ; 01-12 ! 710: * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year ! 711: * ! 712: * time-hour = 2DIGIT ; 00-23 ! 713: * time-minute = 2DIGIT ; 00-59 ! 714: * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules ! 715: * ! 716: * time-secfrac = "." 1*DIGIT ! 717: * time-numoffset = ("+" / "-") time-hour ":" time-minute ! 718: * time-offset = "Z" / time-numoffset ! 719: * ! 720: * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] ! 721: * full-date = date-fullyear "-" date-month "-" date-mday ! 722: * full-time = partial-time time-offset ! 723: * ! 724: * date-time = full-date "T" full-time ! 725: */ ! 726: #define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP" ! 727: ! 728: #define DATE_FORMAT_ISO8601 "Y-m-d\\TH:i:sO" ! 729: ! 730: #define DATE_TZ_ERRMSG \ ! 731: "It is not safe to rely on the system's timezone settings. You are " \ ! 732: "*required* to use the date.timezone setting or the " \ ! 733: "date_default_timezone_set() function. In case you used any of those " \ ! 734: "methods and you are still getting this warning, you most likely " \ ! 735: "misspelled the timezone identifier. " ! 736: ! 737: #define SUNFUNCS_RET_TIMESTAMP 0 ! 738: #define SUNFUNCS_RET_STRING 1 ! 739: #define SUNFUNCS_RET_DOUBLE 2 ! 740: ! 741: ! 742: /* {{{ PHP_MINIT_FUNCTION */ ! 743: PHP_MINIT_FUNCTION(date) ! 744: { ! 745: REGISTER_INI_ENTRIES(); ! 746: date_register_classes(TSRMLS_C); ! 747: /* ! 748: * RFC4287, Section 3.3: http://www.ietf.org/rfc/rfc4287.txt ! 749: * A Date construct is an element whose content MUST conform to the ! 750: * "date-time" production in [RFC3339]. In addition, an uppercase "T" ! 751: * character MUST be used to separate date and time, and an uppercase ! 752: * "Z" character MUST be present in the absence of a numeric time zone offset. ! 753: */ ! 754: REGISTER_STRING_CONSTANT("DATE_ATOM", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); ! 755: /* ! 756: * Preliminary specification: http://wp.netscape.com/newsref/std/cookie_spec.html ! 757: * "This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, ! 758: * with the variations that the only legal time zone is GMT ! 759: * and the separators between the elements of the date must be dashes." ! 760: */ ! 761: REGISTER_STRING_CONSTANT("DATE_COOKIE", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); ! 762: REGISTER_STRING_CONSTANT("DATE_ISO8601", DATE_FORMAT_ISO8601, CONST_CS | CONST_PERSISTENT); ! 763: REGISTER_STRING_CONSTANT("DATE_RFC822", DATE_FORMAT_RFC822, CONST_CS | CONST_PERSISTENT); ! 764: REGISTER_STRING_CONSTANT("DATE_RFC850", DATE_FORMAT_RFC850, CONST_CS | CONST_PERSISTENT); ! 765: REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT); ! 766: REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); ! 767: REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT); ! 768: REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); ! 769: /* ! 770: * RSS 2.0 Specification: http://blogs.law.harvard.edu/tech/rss ! 771: * "All date-times in RSS conform to the Date and Time Specification of RFC 822, ! 772: * with the exception that the year may be expressed with two characters or four characters (four preferred)" ! 773: */ ! 774: REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT); ! 775: REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT); ! 776: ! 777: REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_CS | CONST_PERSISTENT); ! 778: REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_CS | CONST_PERSISTENT); ! 779: REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_CS | CONST_PERSISTENT); ! 780: ! 781: php_date_global_timezone_db = NULL; ! 782: php_date_global_timezone_db_enabled = 0; ! 783: DATEG(last_errors) = NULL; ! 784: return SUCCESS; ! 785: } ! 786: /* }}} */ ! 787: ! 788: /* {{{ PHP_MSHUTDOWN_FUNCTION */ ! 789: PHP_MSHUTDOWN_FUNCTION(date) ! 790: { ! 791: UNREGISTER_INI_ENTRIES(); ! 792: ! 793: if (DATEG(last_errors)) { ! 794: timelib_error_container_dtor(DATEG(last_errors)); ! 795: } ! 796: ! 797: return SUCCESS; ! 798: } ! 799: /* }}} */ ! 800: ! 801: /* {{{ PHP_MINFO_FUNCTION */ ! 802: PHP_MINFO_FUNCTION(date) ! 803: { ! 804: const timelib_tzdb *tzdb = DATE_TIMEZONEDB; ! 805: ! 806: php_info_print_table_start(); ! 807: php_info_print_table_row(2, "date/time support", "enabled"); ! 808: php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version); ! 809: php_info_print_table_row(2, "Timezone Database", php_date_global_timezone_db_enabled ? "external" : "internal"); ! 810: php_info_print_table_row(2, "Default timezone", guess_timezone(tzdb TSRMLS_CC)); ! 811: php_info_print_table_end(); ! 812: ! 813: DISPLAY_INI_ENTRIES(); ! 814: } ! 815: /* }}} */ ! 816: ! 817: /* {{{ Timezone Cache functions */ ! 818: static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, const timelib_tzdb *tzdb TSRMLS_DC) ! 819: { ! 820: timelib_tzinfo *tzi, **ptzi; ! 821: ! 822: if(!DATEG(tzcache)) { ! 823: ALLOC_HASHTABLE(DATEG(tzcache)); ! 824: zend_hash_init(DATEG(tzcache), 4, NULL, _php_date_tzinfo_dtor, 0); ! 825: } ! 826: ! 827: if (zend_hash_find(DATEG(tzcache), formal_tzname, strlen(formal_tzname) + 1, (void **) &ptzi) == SUCCESS) { ! 828: return *ptzi; ! 829: } ! 830: ! 831: tzi = timelib_parse_tzfile(formal_tzname, tzdb); ! 832: if (tzi) { ! 833: zend_hash_add(DATEG(tzcache), formal_tzname, strlen(formal_tzname) + 1, (void *) &tzi, sizeof(timelib_tzinfo*), NULL); ! 834: } ! 835: return tzi; ! 836: } ! 837: ! 838: timelib_tzinfo *php_date_parse_tzfile_wrapper(char *formal_tzname, const timelib_tzdb *tzdb) ! 839: { ! 840: TSRMLS_FETCH(); ! 841: return php_date_parse_tzfile(formal_tzname, tzdb TSRMLS_CC); ! 842: } ! 843: /* }}} */ ! 844: ! 845: /* {{{ Helper functions */ ! 846: static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC) ! 847: { ! 848: char *env; ! 849: ! 850: /* Checking configure timezone */ ! 851: if (DATEG(timezone) && (strlen(DATEG(timezone)) > 0)) { ! 852: return DATEG(timezone); ! 853: } ! 854: /* Check environment variable */ ! 855: env = getenv("TZ"); ! 856: if (env && *env && timelib_timezone_id_is_valid(env, tzdb)) { ! 857: return env; ! 858: } ! 859: /* Check config setting for default timezone */ ! 860: if (!DATEG(default_timezone)) { ! 861: /* Special case: ext/date wasn't initialized yet */ ! 862: zval ztz; ! 863: ! 864: if (SUCCESS == zend_get_configuration_directive("date.timezone", sizeof("date.timezone"), &ztz) && ! 865: Z_TYPE(ztz) == IS_STRING && ! 866: Z_STRLEN(ztz) > 0 && ! 867: timelib_timezone_id_is_valid(Z_STRVAL(ztz), tzdb)) { ! 868: return Z_STRVAL(ztz); ! 869: } ! 870: } else if (*DATEG(default_timezone) && timelib_timezone_id_is_valid(DATEG(default_timezone), tzdb)) { ! 871: return DATEG(default_timezone); ! 872: } ! 873: #if HAVE_TM_ZONE ! 874: /* Try to guess timezone from system information */ ! 875: { ! 876: struct tm *ta, tmbuf; ! 877: time_t the_time; ! 878: char *tzid = NULL; ! 879: ! 880: the_time = time(NULL); ! 881: ta = php_localtime_r(&the_time, &tmbuf); ! 882: if (ta) { ! 883: tzid = timelib_timezone_id_from_abbr(ta->tm_zone, ta->tm_gmtoff, ta->tm_isdst); ! 884: } ! 885: if (! tzid) { ! 886: tzid = "UTC"; ! 887: } ! 888: ! 889: php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%s/%.1f/%s' instead", tzid, ta ? ta->tm_zone : "Unknown", ta ? (float) (ta->tm_gmtoff / 3600) : 0, ta ? (ta->tm_isdst ? "DST" : "no DST") : "Unknown"); ! 890: return tzid; ! 891: } ! 892: #endif ! 893: #ifdef PHP_WIN32 ! 894: { ! 895: char *tzid; ! 896: TIME_ZONE_INFORMATION tzi; ! 897: ! 898: switch (GetTimeZoneInformation(&tzi)) ! 899: { ! 900: /* DST in effect */ ! 901: case TIME_ZONE_ID_DAYLIGHT: ! 902: /* If user has disabled DST in the control panel, Windows returns 0 here */ ! 903: if (tzi.DaylightBias == 0) { ! 904: goto php_win_std_time; ! 905: } ! 906: ! 907: tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.DaylightBias) * -60, 1); ! 908: if (! tzid) { ! 909: tzid = "UTC"; ! 910: } ! 911: php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/DST' instead", tzid, ((tzi.Bias + tzi.DaylightBias) / -60.0)); ! 912: break; ! 913: ! 914: /* no DST or not in effect */ ! 915: case TIME_ZONE_ID_UNKNOWN: ! 916: case TIME_ZONE_ID_STANDARD: ! 917: default: ! 918: php_win_std_time: ! 919: tzid = timelib_timezone_id_from_abbr("", (tzi.Bias + tzi.StandardBias) * -60, 0); ! 920: if (! tzid) { ! 921: tzid = "UTC"; ! 922: } ! 923: php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We selected '%s' for '%.1f/no DST' instead", tzid, ((tzi.Bias + tzi.StandardBias) / -60.0)); ! 924: break; ! 925: ! 926: } ! 927: return tzid; ! 928: } ! 929: #elif defined(NETWARE) ! 930: /* Try to guess timezone from system information */ ! 931: { ! 932: char *tzid = timelib_timezone_id_from_abbr("", ((_timezone * -1) + (daylightOffset * daylightOnOff)), daylightOnOff); ! 933: if (tzid) { ! 934: return tzid; ! 935: } ! 936: } ! 937: #endif ! 938: /* Fallback to UTC */ ! 939: php_error_docref(NULL TSRMLS_CC, E_WARNING, DATE_TZ_ERRMSG "We had to select 'UTC' because your platform doesn't provide functionality for the guessing algorithm"); ! 940: return "UTC"; ! 941: } ! 942: ! 943: PHPAPI timelib_tzinfo *get_timezone_info(TSRMLS_D) ! 944: { ! 945: char *tz; ! 946: timelib_tzinfo *tzi; ! 947: ! 948: tz = guess_timezone(DATE_TIMEZONEDB TSRMLS_CC); ! 949: tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC); ! 950: if (! tzi) { ! 951: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Timezone database is corrupt - this should *never* happen!"); ! 952: } ! 953: return tzi; ! 954: } ! 955: /* }}} */ ! 956: ! 957: ! 958: /* {{{ date() and gmdate() data */ ! 959: #include "ext/standard/php_smart_str.h" ! 960: ! 961: static char *mon_full_names[] = { ! 962: "January", "February", "March", "April", ! 963: "May", "June", "July", "August", ! 964: "September", "October", "November", "December" ! 965: }; ! 966: ! 967: static char *mon_short_names[] = { ! 968: "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ! 969: }; ! 970: ! 971: static char *day_full_names[] = { ! 972: "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ! 973: }; ! 974: ! 975: static char *day_short_names[] = { ! 976: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ! 977: }; ! 978: ! 979: static char *english_suffix(timelib_sll number) ! 980: { ! 981: if (number >= 10 && number <= 19) { ! 982: return "th"; ! 983: } else { ! 984: switch (number % 10) { ! 985: case 1: return "st"; ! 986: case 2: return "nd"; ! 987: case 3: return "rd"; ! 988: } ! 989: } ! 990: return "th"; ! 991: } ! 992: /* }}} */ ! 993: ! 994: /* {{{ day of week helpers */ ! 995: char *php_date_full_day_name(timelib_sll y, timelib_sll m, timelib_sll d) ! 996: { ! 997: timelib_sll day_of_week = timelib_day_of_week(y, m, d); ! 998: if (day_of_week < 0) { ! 999: return "Unknown"; ! 1000: } ! 1001: return day_full_names[day_of_week]; ! 1002: } ! 1003: ! 1004: char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d) ! 1005: { ! 1006: timelib_sll day_of_week = timelib_day_of_week(y, m, d); ! 1007: if (day_of_week < 0) { ! 1008: return "Unknown"; ! 1009: } ! 1010: return day_short_names[day_of_week]; ! 1011: } ! 1012: /* }}} */ ! 1013: ! 1014: /* {{{ date_format - (gm)date helper */ ! 1015: static char *date_format(char *format, int format_len, timelib_time *t, int localtime) ! 1016: { ! 1017: smart_str string = {0}; ! 1018: int i, length; ! 1019: char buffer[97]; ! 1020: timelib_time_offset *offset = NULL; ! 1021: timelib_sll isoweek, isoyear; ! 1022: int rfc_colon; ! 1023: ! 1024: if (!format_len) { ! 1025: return estrdup(""); ! 1026: } ! 1027: ! 1028: if (localtime) { ! 1029: if (t->zone_type == TIMELIB_ZONETYPE_ABBR) { ! 1030: offset = timelib_time_offset_ctor(); ! 1031: offset->offset = (t->z - (t->dst * 60)) * -60; ! 1032: offset->leap_secs = 0; ! 1033: offset->is_dst = t->dst; ! 1034: offset->abbr = strdup(t->tz_abbr); ! 1035: } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) { ! 1036: offset = timelib_time_offset_ctor(); ! 1037: offset->offset = (t->z) * -60; ! 1038: offset->leap_secs = 0; ! 1039: offset->is_dst = 0; ! 1040: offset->abbr = malloc(9); /* GMT�xxxx\0 */ ! 1041: snprintf(offset->abbr, 9, "GMT%c%02d%02d", ! 1042: localtime ? ((offset->offset < 0) ? '-' : '+') : '+', ! 1043: localtime ? abs(offset->offset / 3600) : 0, ! 1044: localtime ? abs((offset->offset % 3600) / 60) : 0 ); ! 1045: } else { ! 1046: offset = timelib_get_time_zone_info(t->sse, t->tz_info); ! 1047: } ! 1048: } ! 1049: timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); ! 1050: ! 1051: for (i = 0; i < format_len; i++) { ! 1052: rfc_colon = 0; ! 1053: switch (format[i]) { ! 1054: /* day */ ! 1055: case 'd': length = slprintf(buffer, 32, "%02d", (int) t->d); break; ! 1056: case 'D': length = slprintf(buffer, 32, "%s", php_date_short_day_name(t->y, t->m, t->d)); break; ! 1057: case 'j': length = slprintf(buffer, 32, "%d", (int) t->d); break; ! 1058: case 'l': length = slprintf(buffer, 32, "%s", php_date_full_day_name(t->y, t->m, t->d)); break; ! 1059: case 'S': length = slprintf(buffer, 32, "%s", english_suffix(t->d)); break; ! 1060: case 'w': length = slprintf(buffer, 32, "%d", (int) timelib_day_of_week(t->y, t->m, t->d)); break; ! 1061: case 'N': length = slprintf(buffer, 32, "%d", (int) timelib_iso_day_of_week(t->y, t->m, t->d)); break; ! 1062: case 'z': length = slprintf(buffer, 32, "%d", (int) timelib_day_of_year(t->y, t->m, t->d)); break; ! 1063: ! 1064: /* week */ ! 1065: case 'W': length = slprintf(buffer, 32, "%02d", (int) isoweek); break; /* iso weeknr */ ! 1066: case 'o': length = slprintf(buffer, 32, "%d", (int) isoyear); break; /* iso year */ ! 1067: ! 1068: /* month */ ! 1069: case 'F': length = slprintf(buffer, 32, "%s", mon_full_names[t->m - 1]); break; ! 1070: case 'm': length = slprintf(buffer, 32, "%02d", (int) t->m); break; ! 1071: case 'M': length = slprintf(buffer, 32, "%s", mon_short_names[t->m - 1]); break; ! 1072: case 'n': length = slprintf(buffer, 32, "%d", (int) t->m); break; ! 1073: case 't': length = slprintf(buffer, 32, "%d", (int) timelib_days_in_month(t->y, t->m)); break; ! 1074: ! 1075: /* year */ ! 1076: case 'L': length = slprintf(buffer, 32, "%d", timelib_is_leap((int) t->y)); break; ! 1077: case 'y': length = slprintf(buffer, 32, "%02d", (int) t->y % 100); break; ! 1078: case 'Y': length = slprintf(buffer, 32, "%s%04lld", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break; ! 1079: ! 1080: /* time */ ! 1081: case 'a': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break; ! 1082: case 'A': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break; ! 1083: case 'B': { ! 1084: int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); ! 1085: while (retval < 0) { ! 1086: retval += 1000; ! 1087: } ! 1088: retval = retval % 1000; ! 1089: length = slprintf(buffer, 32, "%03d", retval); ! 1090: break; ! 1091: } ! 1092: case 'g': length = slprintf(buffer, 32, "%d", (t->h % 12) ? (int) t->h % 12 : 12); break; ! 1093: case 'G': length = slprintf(buffer, 32, "%d", (int) t->h); break; ! 1094: case 'h': length = slprintf(buffer, 32, "%02d", (t->h % 12) ? (int) t->h % 12 : 12); break; ! 1095: case 'H': length = slprintf(buffer, 32, "%02d", (int) t->h); break; ! 1096: case 'i': length = slprintf(buffer, 32, "%02d", (int) t->i); break; ! 1097: case 's': length = slprintf(buffer, 32, "%02d", (int) t->s); break; ! 1098: case 'u': length = slprintf(buffer, 32, "%06d", (int) floor(t->f * 1000000)); break; ! 1099: ! 1100: /* timezone */ ! 1101: case 'I': length = slprintf(buffer, 32, "%d", localtime ? offset->is_dst : 0); break; ! 1102: case 'P': rfc_colon = 1; /* break intentionally missing */ ! 1103: case 'O': length = slprintf(buffer, 32, "%c%02d%s%02d", ! 1104: localtime ? ((offset->offset < 0) ? '-' : '+') : '+', ! 1105: localtime ? abs(offset->offset / 3600) : 0, ! 1106: rfc_colon ? ":" : "", ! 1107: localtime ? abs((offset->offset % 3600) / 60) : 0 ! 1108: ); ! 1109: break; ! 1110: case 'T': length = slprintf(buffer, 32, "%s", localtime ? offset->abbr : "GMT"); break; ! 1111: case 'e': if (!localtime) { ! 1112: length = slprintf(buffer, 32, "%s", "UTC"); ! 1113: } else { ! 1114: switch (t->zone_type) { ! 1115: case TIMELIB_ZONETYPE_ID: ! 1116: length = slprintf(buffer, 32, "%s", t->tz_info->name); ! 1117: break; ! 1118: case TIMELIB_ZONETYPE_ABBR: ! 1119: length = slprintf(buffer, 32, "%s", offset->abbr); ! 1120: break; ! 1121: case TIMELIB_ZONETYPE_OFFSET: ! 1122: length = slprintf(buffer, 32, "%c%02d:%02d", ! 1123: ((offset->offset < 0) ? '-' : '+'), ! 1124: abs(offset->offset / 3600), ! 1125: abs((offset->offset % 3600) / 60) ! 1126: ); ! 1127: break; ! 1128: } ! 1129: } ! 1130: break; ! 1131: case 'Z': length = slprintf(buffer, 32, "%d", localtime ? offset->offset : 0); break; ! 1132: ! 1133: /* full date/time */ ! 1134: case 'c': length = slprintf(buffer, 96, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", ! 1135: (int) t->y, (int) t->m, (int) t->d, ! 1136: (int) t->h, (int) t->i, (int) t->s, ! 1137: localtime ? ((offset->offset < 0) ? '-' : '+') : '+', ! 1138: localtime ? abs(offset->offset / 3600) : 0, ! 1139: localtime ? abs((offset->offset % 3600) / 60) : 0 ! 1140: ); ! 1141: break; ! 1142: case 'r': length = slprintf(buffer, 96, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d", ! 1143: php_date_short_day_name(t->y, t->m, t->d), ! 1144: (int) t->d, mon_short_names[t->m - 1], ! 1145: (int) t->y, (int) t->h, (int) t->i, (int) t->s, ! 1146: localtime ? ((offset->offset < 0) ? '-' : '+') : '+', ! 1147: localtime ? abs(offset->offset / 3600) : 0, ! 1148: localtime ? abs((offset->offset % 3600) / 60) : 0 ! 1149: ); ! 1150: break; ! 1151: case 'U': length = slprintf(buffer, 32, "%lld", (timelib_sll) t->sse); break; ! 1152: ! 1153: case '\\': if (i < format_len) i++; /* break intentionally missing */ ! 1154: ! 1155: default: buffer[0] = format[i]; buffer[1] = '\0'; length = 1; break; ! 1156: } ! 1157: smart_str_appendl(&string, buffer, length); ! 1158: } ! 1159: ! 1160: smart_str_0(&string); ! 1161: ! 1162: if (localtime) { ! 1163: timelib_time_offset_dtor(offset); ! 1164: } ! 1165: ! 1166: return string.c; ! 1167: } ! 1168: ! 1169: static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime) ! 1170: { ! 1171: char *format; ! 1172: int format_len; ! 1173: long ts; ! 1174: char *string; ! 1175: ! 1176: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) { ! 1177: RETURN_FALSE; ! 1178: } ! 1179: if (ZEND_NUM_ARGS() == 1) { ! 1180: ts = time(NULL); ! 1181: } ! 1182: ! 1183: string = php_format_date(format, format_len, ts, localtime TSRMLS_CC); ! 1184: ! 1185: RETVAL_STRING(string, 0); ! 1186: } ! 1187: /* }}} */ ! 1188: ! 1189: PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localtime TSRMLS_DC) /* {{{ */ ! 1190: { ! 1191: timelib_time *t; ! 1192: timelib_tzinfo *tzi; ! 1193: char *string; ! 1194: ! 1195: t = timelib_time_ctor(); ! 1196: ! 1197: if (localtime) { ! 1198: tzi = get_timezone_info(TSRMLS_C); ! 1199: t->tz_info = tzi; ! 1200: t->zone_type = TIMELIB_ZONETYPE_ID; ! 1201: timelib_unixtime2local(t, ts); ! 1202: } else { ! 1203: tzi = NULL; ! 1204: timelib_unixtime2gmt(t, ts); ! 1205: } ! 1206: ! 1207: string = date_format(format, format_len, t, localtime); ! 1208: ! 1209: timelib_time_dtor(t); ! 1210: return string; ! 1211: } ! 1212: /* }}} */ ! 1213: ! 1214: /* {{{ php_idate ! 1215: */ ! 1216: PHPAPI int php_idate(char format, time_t ts, int localtime) ! 1217: { ! 1218: timelib_time *t; ! 1219: timelib_tzinfo *tzi; ! 1220: int retval = -1; ! 1221: timelib_time_offset *offset = NULL; ! 1222: timelib_sll isoweek, isoyear; ! 1223: TSRMLS_FETCH(); ! 1224: ! 1225: t = timelib_time_ctor(); ! 1226: ! 1227: if (!localtime) { ! 1228: tzi = get_timezone_info(TSRMLS_C); ! 1229: t->tz_info = tzi; ! 1230: t->zone_type = TIMELIB_ZONETYPE_ID; ! 1231: timelib_unixtime2local(t, ts); ! 1232: } else { ! 1233: tzi = NULL; ! 1234: timelib_unixtime2gmt(t, ts); ! 1235: } ! 1236: ! 1237: if (!localtime) { ! 1238: if (t->zone_type == TIMELIB_ZONETYPE_ABBR) { ! 1239: offset = timelib_time_offset_ctor(); ! 1240: offset->offset = (t->z - (t->dst * 60)) * -60; ! 1241: offset->leap_secs = 0; ! 1242: offset->is_dst = t->dst; ! 1243: offset->abbr = strdup(t->tz_abbr); ! 1244: } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) { ! 1245: offset = timelib_time_offset_ctor(); ! 1246: offset->offset = (t->z - (t->dst * 60)) * -60; ! 1247: offset->leap_secs = 0; ! 1248: offset->is_dst = t->dst; ! 1249: offset->abbr = malloc(9); /* GMT�xxxx\0 */ ! 1250: snprintf(offset->abbr, 9, "GMT%c%02d%02d", ! 1251: !localtime ? ((offset->offset < 0) ? '-' : '+') : '+', ! 1252: !localtime ? abs(offset->offset / 3600) : 0, ! 1253: !localtime ? abs((offset->offset % 3600) / 60) : 0 ); ! 1254: } else { ! 1255: offset = timelib_get_time_zone_info(t->sse, t->tz_info); ! 1256: } ! 1257: } ! 1258: ! 1259: timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); ! 1260: ! 1261: switch (format) { ! 1262: /* day */ ! 1263: case 'd': case 'j': retval = (int) t->d; break; ! 1264: ! 1265: case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break; ! 1266: case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break; ! 1267: ! 1268: /* week */ ! 1269: case 'W': retval = (int) isoweek; break; /* iso weeknr */ ! 1270: ! 1271: /* month */ ! 1272: case 'm': case 'n': retval = (int) t->m; break; ! 1273: case 't': retval = (int) timelib_days_in_month(t->y, t->m); break; ! 1274: ! 1275: /* year */ ! 1276: case 'L': retval = (int) timelib_is_leap((int) t->y); break; ! 1277: case 'y': retval = (int) (t->y % 100); break; ! 1278: case 'Y': retval = (int) t->y; break; ! 1279: ! 1280: /* Swatch Beat a.k.a. Internet Time */ ! 1281: case 'B': ! 1282: retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); ! 1283: while (retval < 0) { ! 1284: retval += 1000; ! 1285: } ! 1286: retval = retval % 1000; ! 1287: break; ! 1288: ! 1289: /* time */ ! 1290: case 'g': case 'h': retval = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break; ! 1291: case 'H': case 'G': retval = (int) t->h; break; ! 1292: case 'i': retval = (int) t->i; break; ! 1293: case 's': retval = (int) t->s; break; ! 1294: ! 1295: /* timezone */ ! 1296: case 'I': retval = (int) (!localtime ? offset->is_dst : 0); break; ! 1297: case 'Z': retval = (int) (!localtime ? offset->offset : 0); break; ! 1298: ! 1299: case 'U': retval = (int) t->sse; break; ! 1300: } ! 1301: ! 1302: if (!localtime) { ! 1303: timelib_time_offset_dtor(offset); ! 1304: } ! 1305: timelib_time_dtor(t); ! 1306: ! 1307: return retval; ! 1308: } ! 1309: /* }}} */ ! 1310: ! 1311: /* {{{ proto string date(string format [, long timestamp]) ! 1312: Format a local date/time */ ! 1313: PHP_FUNCTION(date) ! 1314: { ! 1315: php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ! 1316: } ! 1317: /* }}} */ ! 1318: ! 1319: /* {{{ proto string gmdate(string format [, long timestamp]) ! 1320: Format a GMT date/time */ ! 1321: PHP_FUNCTION(gmdate) ! 1322: { ! 1323: php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); ! 1324: } ! 1325: /* }}} */ ! 1326: ! 1327: /* {{{ proto int idate(string format [, int timestamp]) ! 1328: Format a local time/date as integer */ ! 1329: PHP_FUNCTION(idate) ! 1330: { ! 1331: char *format; ! 1332: int format_len; ! 1333: long ts = 0; ! 1334: int ret; ! 1335: ! 1336: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) { ! 1337: RETURN_FALSE; ! 1338: } ! 1339: ! 1340: if (format_len != 1) { ! 1341: php_error_docref(NULL TSRMLS_CC, E_WARNING, "idate format is one char"); ! 1342: RETURN_FALSE; ! 1343: } ! 1344: ! 1345: if (ZEND_NUM_ARGS() == 1) { ! 1346: ts = time(NULL); ! 1347: } ! 1348: ! 1349: ret = php_idate(format[0], ts, 0); ! 1350: if (ret == -1) { ! 1351: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized date format token."); ! 1352: RETURN_FALSE; ! 1353: } ! 1354: RETURN_LONG(ret); ! 1355: } ! 1356: /* }}} */ ! 1357: ! 1358: /* {{{ php_date_set_tzdb - NOT THREADSAFE */ ! 1359: PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb) ! 1360: { ! 1361: const timelib_tzdb *builtin = timelib_builtin_db(); ! 1362: ! 1363: if (php_version_compare(tzdb->version, builtin->version) > 0) { ! 1364: php_date_global_timezone_db = tzdb; ! 1365: php_date_global_timezone_db_enabled = 1; ! 1366: } ! 1367: } ! 1368: /* }}} */ ! 1369: ! 1370: /* {{{ php_parse_date: Backwards compability function */ ! 1371: PHPAPI signed long php_parse_date(char *string, signed long *now) ! 1372: { ! 1373: timelib_time *parsed_time; ! 1374: timelib_error_container *error = NULL; ! 1375: int error2; ! 1376: signed long retval; ! 1377: ! 1378: parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 1379: if (error->error_count) { ! 1380: timelib_error_container_dtor(error); ! 1381: return -1; ! 1382: } ! 1383: timelib_error_container_dtor(error); ! 1384: timelib_update_ts(parsed_time, NULL); ! 1385: retval = timelib_date_to_int(parsed_time, &error2); ! 1386: timelib_time_dtor(parsed_time); ! 1387: if (error2) { ! 1388: return -1; ! 1389: } ! 1390: return retval; ! 1391: } ! 1392: /* }}} */ ! 1393: ! 1394: ! 1395: /* {{{ proto int strtotime(string time [, int now ]) ! 1396: Convert string representation of date and time to a timestamp */ ! 1397: PHP_FUNCTION(strtotime) ! 1398: { ! 1399: char *times, *initial_ts; ! 1400: int time_len, error1, error2; ! 1401: struct timelib_error_container *error; ! 1402: long preset_ts = 0, ts; ! 1403: ! 1404: timelib_time *t, *now; ! 1405: timelib_tzinfo *tzi; ! 1406: ! 1407: tzi = get_timezone_info(TSRMLS_C); ! 1408: ! 1409: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sl", ×, &time_len, &preset_ts) != FAILURE) { ! 1410: /* We have an initial timestamp */ ! 1411: now = timelib_time_ctor(); ! 1412: ! 1413: initial_ts = emalloc(25); ! 1414: snprintf(initial_ts, 24, "@%ld UTC", preset_ts); ! 1415: t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); /* we ignore the error here, as this should never fail */ ! 1416: timelib_update_ts(t, tzi); ! 1417: now->tz_info = tzi; ! 1418: now->zone_type = TIMELIB_ZONETYPE_ID; ! 1419: timelib_unixtime2local(now, t->sse); ! 1420: timelib_time_dtor(t); ! 1421: efree(initial_ts); ! 1422: } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", ×, &time_len, &preset_ts) != FAILURE) { ! 1423: /* We have no initial timestamp */ ! 1424: now = timelib_time_ctor(); ! 1425: now->tz_info = tzi; ! 1426: now->zone_type = TIMELIB_ZONETYPE_ID; ! 1427: timelib_unixtime2local(now, (timelib_sll) time(NULL)); ! 1428: } else { ! 1429: RETURN_FALSE; ! 1430: } ! 1431: ! 1432: if (!time_len) { ! 1433: timelib_time_dtor(now); ! 1434: RETURN_FALSE; ! 1435: } ! 1436: ! 1437: t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 1438: error1 = error->error_count; ! 1439: timelib_error_container_dtor(error); ! 1440: timelib_fill_holes(t, now, TIMELIB_NO_CLONE); ! 1441: timelib_update_ts(t, tzi); ! 1442: ts = timelib_date_to_int(t, &error2); ! 1443: ! 1444: timelib_time_dtor(now); ! 1445: timelib_time_dtor(t); ! 1446: ! 1447: if (error1 || error2) { ! 1448: RETURN_FALSE; ! 1449: } else { ! 1450: RETURN_LONG(ts); ! 1451: } ! 1452: } ! 1453: /* }}} */ ! 1454: ! 1455: ! 1456: /* {{{ php_mktime - (gm)mktime helper */ ! 1457: PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt) ! 1458: { ! 1459: long hou = 0, min = 0, sec = 0, mon = 0, day = 0, yea = 0, dst = -1; ! 1460: timelib_time *now; ! 1461: timelib_tzinfo *tzi = NULL; ! 1462: long ts, adjust_seconds = 0; ! 1463: int error; ! 1464: ! 1465: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lllllll", &hou, &min, &sec, &mon, &day, &yea, &dst) == FAILURE) { ! 1466: RETURN_FALSE; ! 1467: } ! 1468: /* Initialize structure with current time */ ! 1469: now = timelib_time_ctor(); ! 1470: if (gmt) { ! 1471: timelib_unixtime2gmt(now, (timelib_sll) time(NULL)); ! 1472: } else { ! 1473: tzi = get_timezone_info(TSRMLS_C); ! 1474: now->tz_info = tzi; ! 1475: now->zone_type = TIMELIB_ZONETYPE_ID; ! 1476: timelib_unixtime2local(now, (timelib_sll) time(NULL)); ! 1477: } ! 1478: /* Fill in the new data */ ! 1479: switch (ZEND_NUM_ARGS()) { ! 1480: case 7: ! 1481: /* break intentionally missing */ ! 1482: case 6: ! 1483: if (yea >= 0 && yea < 70) { ! 1484: yea += 2000; ! 1485: } else if (yea >= 70 && yea <= 100) { ! 1486: yea += 1900; ! 1487: } ! 1488: now->y = yea; ! 1489: /* break intentionally missing again */ ! 1490: case 5: ! 1491: now->d = day; ! 1492: /* break missing intentionally here too */ ! 1493: case 4: ! 1494: now->m = mon; ! 1495: /* and here */ ! 1496: case 3: ! 1497: now->s = sec; ! 1498: /* yup, this break isn't here on purpose too */ ! 1499: case 2: ! 1500: now->i = min; ! 1501: /* last intentionally missing break */ ! 1502: case 1: ! 1503: now->h = hou; ! 1504: break; ! 1505: default: ! 1506: php_error_docref(NULL TSRMLS_CC, E_STRICT, "You should be using the time() function instead"); ! 1507: } ! 1508: /* Update the timestamp */ ! 1509: if (gmt) { ! 1510: timelib_update_ts(now, NULL); ! 1511: } else { ! 1512: timelib_update_ts(now, tzi); ! 1513: } ! 1514: /* Support for the deprecated is_dst parameter */ ! 1515: if (dst != -1) { ! 1516: php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The is_dst parameter is deprecated"); ! 1517: if (gmt) { ! 1518: /* GMT never uses DST */ ! 1519: if (dst == 1) { ! 1520: adjust_seconds = -3600; ! 1521: } ! 1522: } else { ! 1523: /* Figure out is_dst for current TS */ ! 1524: timelib_time_offset *tmp_offset; ! 1525: tmp_offset = timelib_get_time_zone_info(now->sse, tzi); ! 1526: if (dst == 1 && tmp_offset->is_dst == 0) { ! 1527: adjust_seconds = -3600; ! 1528: } ! 1529: if (dst == 0 && tmp_offset->is_dst == 1) { ! 1530: adjust_seconds = +3600; ! 1531: } ! 1532: timelib_time_offset_dtor(tmp_offset); ! 1533: } ! 1534: } ! 1535: /* Clean up and return */ ! 1536: ts = timelib_date_to_int(now, &error); ! 1537: ts += adjust_seconds; ! 1538: timelib_time_dtor(now); ! 1539: ! 1540: if (error) { ! 1541: RETURN_FALSE; ! 1542: } else { ! 1543: RETURN_LONG(ts); ! 1544: } ! 1545: } ! 1546: /* }}} */ ! 1547: ! 1548: /* {{{ proto int mktime([int hour [, int min [, int sec [, int mon [, int day [, int year]]]]]]) ! 1549: Get UNIX timestamp for a date */ ! 1550: PHP_FUNCTION(mktime) ! 1551: { ! 1552: php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); ! 1553: } ! 1554: /* }}} */ ! 1555: ! 1556: /* {{{ proto int gmmktime([int hour [, int min [, int sec [, int mon [, int day [, int year]]]]]]) ! 1557: Get UNIX timestamp for a GMT date */ ! 1558: PHP_FUNCTION(gmmktime) ! 1559: { ! 1560: php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ! 1561: } ! 1562: /* }}} */ ! 1563: ! 1564: ! 1565: /* {{{ proto bool checkdate(int month, int day, int year) ! 1566: Returns true(1) if it is a valid date in gregorian calendar */ ! 1567: PHP_FUNCTION(checkdate) ! 1568: { ! 1569: long m, d, y; ! 1570: ! 1571: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &m, &d, &y) == FAILURE) { ! 1572: RETURN_FALSE; ! 1573: } ! 1574: ! 1575: if (y < 1 || y > 32767 || !timelib_valid_date(y, m, d)) { ! 1576: RETURN_FALSE; ! 1577: } ! 1578: RETURN_TRUE; /* True : This month, day, year arguments are valid */ ! 1579: } ! 1580: /* }}} */ ! 1581: ! 1582: #ifdef HAVE_STRFTIME ! 1583: /* {{{ php_strftime - (gm)strftime helper */ ! 1584: PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gmt) ! 1585: { ! 1586: char *format, *buf; ! 1587: int format_len; ! 1588: long timestamp = 0; ! 1589: struct tm ta; ! 1590: int max_reallocs = 5; ! 1591: size_t buf_len = 64, real_len; ! 1592: timelib_time *ts; ! 1593: timelib_tzinfo *tzi; ! 1594: timelib_time_offset *offset = NULL; ! 1595: ! 1596: timestamp = (long) time(NULL); ! 1597: ! 1598: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, ×tamp) == FAILURE) { ! 1599: RETURN_FALSE; ! 1600: } ! 1601: ! 1602: if (format_len == 0) { ! 1603: RETURN_FALSE; ! 1604: } ! 1605: ! 1606: ts = timelib_time_ctor(); ! 1607: if (gmt) { ! 1608: tzi = NULL; ! 1609: timelib_unixtime2gmt(ts, (timelib_sll) timestamp); ! 1610: } else { ! 1611: tzi = get_timezone_info(TSRMLS_C); ! 1612: ts->tz_info = tzi; ! 1613: ts->zone_type = TIMELIB_ZONETYPE_ID; ! 1614: timelib_unixtime2local(ts, (timelib_sll) timestamp); ! 1615: } ! 1616: ta.tm_sec = ts->s; ! 1617: ta.tm_min = ts->i; ! 1618: ta.tm_hour = ts->h; ! 1619: ta.tm_mday = ts->d; ! 1620: ta.tm_mon = ts->m - 1; ! 1621: ta.tm_year = ts->y - 1900; ! 1622: ta.tm_wday = timelib_day_of_week(ts->y, ts->m, ts->d); ! 1623: ta.tm_yday = timelib_day_of_year(ts->y, ts->m, ts->d); ! 1624: if (gmt) { ! 1625: ta.tm_isdst = 0; ! 1626: #if HAVE_TM_GMTOFF ! 1627: ta.tm_gmtoff = 0; ! 1628: #endif ! 1629: #if HAVE_TM_ZONE ! 1630: ta.tm_zone = "GMT"; ! 1631: #endif ! 1632: } else { ! 1633: offset = timelib_get_time_zone_info(timestamp, tzi); ! 1634: ! 1635: ta.tm_isdst = offset->is_dst; ! 1636: #if HAVE_TM_GMTOFF ! 1637: ta.tm_gmtoff = offset->offset; ! 1638: #endif ! 1639: #if HAVE_TM_ZONE ! 1640: ta.tm_zone = offset->abbr; ! 1641: #endif ! 1642: } ! 1643: ! 1644: buf = (char *) emalloc(buf_len); ! 1645: while ((real_len=strftime(buf, buf_len, format, &ta))==buf_len || real_len==0) { ! 1646: buf_len *= 2; ! 1647: buf = (char *) erealloc(buf, buf_len); ! 1648: if (!--max_reallocs) { ! 1649: break; ! 1650: } ! 1651: } ! 1652: ! 1653: timelib_time_dtor(ts); ! 1654: if (!gmt) { ! 1655: timelib_time_offset_dtor(offset); ! 1656: } ! 1657: ! 1658: if (real_len && real_len != buf_len) { ! 1659: buf = (char *) erealloc(buf, real_len + 1); ! 1660: RETURN_STRINGL(buf, real_len, 0); ! 1661: } ! 1662: efree(buf); ! 1663: RETURN_FALSE; ! 1664: } ! 1665: /* }}} */ ! 1666: ! 1667: /* {{{ proto string strftime(string format [, int timestamp]) ! 1668: Format a local time/date according to locale settings */ ! 1669: PHP_FUNCTION(strftime) ! 1670: { ! 1671: php_strftime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); ! 1672: } ! 1673: /* }}} */ ! 1674: ! 1675: /* {{{ proto string gmstrftime(string format [, int timestamp]) ! 1676: Format a GMT/UCT time/date according to locale settings */ ! 1677: PHP_FUNCTION(gmstrftime) ! 1678: { ! 1679: php_strftime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ! 1680: } ! 1681: /* }}} */ ! 1682: #endif ! 1683: ! 1684: /* {{{ proto int time(void) ! 1685: Return current UNIX timestamp */ ! 1686: PHP_FUNCTION(time) ! 1687: { ! 1688: RETURN_LONG((long)time(NULL)); ! 1689: } ! 1690: /* }}} */ ! 1691: ! 1692: /* {{{ proto array localtime([int timestamp [, bool associative_array]]) ! 1693: Returns the results of the C system call localtime as an associative array if the associative_array argument is set to 1 other wise it is a regular array */ ! 1694: PHP_FUNCTION(localtime) ! 1695: { ! 1696: long timestamp = (long)time(NULL); ! 1697: zend_bool associative = 0; ! 1698: timelib_tzinfo *tzi; ! 1699: timelib_time *ts; ! 1700: ! 1701: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", ×tamp, &associative) == FAILURE) { ! 1702: RETURN_FALSE; ! 1703: } ! 1704: ! 1705: tzi = get_timezone_info(TSRMLS_C); ! 1706: ts = timelib_time_ctor(); ! 1707: ts->tz_info = tzi; ! 1708: ts->zone_type = TIMELIB_ZONETYPE_ID; ! 1709: timelib_unixtime2local(ts, (timelib_sll) timestamp); ! 1710: ! 1711: array_init(return_value); ! 1712: ! 1713: if (associative) { ! 1714: add_assoc_long(return_value, "tm_sec", ts->s); ! 1715: add_assoc_long(return_value, "tm_min", ts->i); ! 1716: add_assoc_long(return_value, "tm_hour", ts->h); ! 1717: add_assoc_long(return_value, "tm_mday", ts->d); ! 1718: add_assoc_long(return_value, "tm_mon", ts->m - 1); ! 1719: add_assoc_long(return_value, "tm_year", ts->y - 1900); ! 1720: add_assoc_long(return_value, "tm_wday", timelib_day_of_week(ts->y, ts->m, ts->d)); ! 1721: add_assoc_long(return_value, "tm_yday", timelib_day_of_year(ts->y, ts->m, ts->d)); ! 1722: add_assoc_long(return_value, "tm_isdst", ts->dst); ! 1723: } else { ! 1724: add_next_index_long(return_value, ts->s); ! 1725: add_next_index_long(return_value, ts->i); ! 1726: add_next_index_long(return_value, ts->h); ! 1727: add_next_index_long(return_value, ts->d); ! 1728: add_next_index_long(return_value, ts->m - 1); ! 1729: add_next_index_long(return_value, ts->y- 1900); ! 1730: add_next_index_long(return_value, timelib_day_of_week(ts->y, ts->m, ts->d)); ! 1731: add_next_index_long(return_value, timelib_day_of_year(ts->y, ts->m, ts->d)); ! 1732: add_next_index_long(return_value, ts->dst); ! 1733: } ! 1734: ! 1735: timelib_time_dtor(ts); ! 1736: } ! 1737: /* }}} */ ! 1738: ! 1739: /* {{{ proto array getdate([int timestamp]) ! 1740: Get date/time information */ ! 1741: PHP_FUNCTION(getdate) ! 1742: { ! 1743: long timestamp = (long)time(NULL); ! 1744: timelib_tzinfo *tzi; ! 1745: timelib_time *ts; ! 1746: ! 1747: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", ×tamp) == FAILURE) { ! 1748: RETURN_FALSE; ! 1749: } ! 1750: ! 1751: tzi = get_timezone_info(TSRMLS_C); ! 1752: ts = timelib_time_ctor(); ! 1753: ts->tz_info = tzi; ! 1754: ts->zone_type = TIMELIB_ZONETYPE_ID; ! 1755: timelib_unixtime2local(ts, (timelib_sll) timestamp); ! 1756: ! 1757: array_init(return_value); ! 1758: ! 1759: add_assoc_long(return_value, "seconds", ts->s); ! 1760: add_assoc_long(return_value, "minutes", ts->i); ! 1761: add_assoc_long(return_value, "hours", ts->h); ! 1762: add_assoc_long(return_value, "mday", ts->d); ! 1763: add_assoc_long(return_value, "wday", timelib_day_of_week(ts->y, ts->m, ts->d)); ! 1764: add_assoc_long(return_value, "mon", ts->m); ! 1765: add_assoc_long(return_value, "year", ts->y); ! 1766: add_assoc_long(return_value, "yday", timelib_day_of_year(ts->y, ts->m, ts->d)); ! 1767: add_assoc_string(return_value, "weekday", php_date_full_day_name(ts->y, ts->m, ts->d), 1); ! 1768: add_assoc_string(return_value, "month", mon_full_names[ts->m - 1], 1); ! 1769: add_index_long(return_value, 0, timestamp); ! 1770: ! 1771: timelib_time_dtor(ts); ! 1772: } ! 1773: /* }}} */ ! 1774: ! 1775: #define PHP_DATE_TIMEZONE_GROUP_AFRICA 0x0001 ! 1776: #define PHP_DATE_TIMEZONE_GROUP_AMERICA 0x0002 ! 1777: #define PHP_DATE_TIMEZONE_GROUP_ANTARCTICA 0x0004 ! 1778: #define PHP_DATE_TIMEZONE_GROUP_ARCTIC 0x0008 ! 1779: #define PHP_DATE_TIMEZONE_GROUP_ASIA 0x0010 ! 1780: #define PHP_DATE_TIMEZONE_GROUP_ATLANTIC 0x0020 ! 1781: #define PHP_DATE_TIMEZONE_GROUP_AUSTRALIA 0x0040 ! 1782: #define PHP_DATE_TIMEZONE_GROUP_EUROPE 0x0080 ! 1783: #define PHP_DATE_TIMEZONE_GROUP_INDIAN 0x0100 ! 1784: #define PHP_DATE_TIMEZONE_GROUP_PACIFIC 0x0200 ! 1785: #define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400 ! 1786: #define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF ! 1787: #define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF ! 1788: #define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000 ! 1789: ! 1790: #define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001 ! 1791: ! 1792: ! 1793: /* define an overloaded iterator structure */ ! 1794: typedef struct { ! 1795: zend_object_iterator intern; ! 1796: zval *date_period_zval; ! 1797: zval *current; ! 1798: php_period_obj *object; ! 1799: int current_index; ! 1800: } date_period_it; ! 1801: ! 1802: /* {{{ date_period_it_invalidate_current */ ! 1803: static void date_period_it_invalidate_current(zend_object_iterator *iter TSRMLS_DC) ! 1804: { ! 1805: date_period_it *iterator = (date_period_it *)iter; ! 1806: ! 1807: if (iterator->current) { ! 1808: zval_ptr_dtor(&iterator->current); ! 1809: iterator->current = NULL; ! 1810: } ! 1811: } ! 1812: /* }}} */ ! 1813: ! 1814: ! 1815: /* {{{ date_period_it_dtor */ ! 1816: static void date_period_it_dtor(zend_object_iterator *iter TSRMLS_DC) ! 1817: { ! 1818: date_period_it *iterator = (date_period_it *)iter; ! 1819: ! 1820: date_period_it_invalidate_current(iter TSRMLS_CC); ! 1821: ! 1822: zval_ptr_dtor(&iterator->date_period_zval); ! 1823: ! 1824: efree(iterator); ! 1825: } ! 1826: /* }}} */ ! 1827: ! 1828: ! 1829: /* {{{ date_period_it_has_more */ ! 1830: static int date_period_it_has_more(zend_object_iterator *iter TSRMLS_DC) ! 1831: { ! 1832: date_period_it *iterator = (date_period_it *)iter; ! 1833: php_period_obj *object = iterator->object; ! 1834: timelib_time *it_time = object->current; ! 1835: ! 1836: /* apply modification if it's not the first iteration */ ! 1837: if (!object->include_start_date || iterator->current_index > 0) { ! 1838: it_time->have_relative = 1; ! 1839: it_time->relative = *object->interval; ! 1840: it_time->sse_uptodate = 0; ! 1841: timelib_update_ts(it_time, NULL); ! 1842: timelib_update_from_sse(it_time); ! 1843: } ! 1844: ! 1845: if (object->end) { ! 1846: return object->current->sse < object->end->sse ? SUCCESS : FAILURE; ! 1847: } else { ! 1848: return (iterator->current_index < object->recurrences) ? SUCCESS : FAILURE; ! 1849: } ! 1850: } ! 1851: /* }}} */ ! 1852: ! 1853: ! 1854: /* {{{ date_period_it_current_data */ ! 1855: static void date_period_it_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) ! 1856: { ! 1857: date_period_it *iterator = (date_period_it *)iter; ! 1858: php_period_obj *object = iterator->object; ! 1859: timelib_time *it_time = object->current; ! 1860: php_date_obj *newdateobj; ! 1861: ! 1862: /* Create new object */ ! 1863: MAKE_STD_ZVAL(iterator->current); ! 1864: php_date_instantiate(date_ce_date, iterator->current TSRMLS_CC); ! 1865: newdateobj = (php_date_obj *) zend_object_store_get_object(iterator->current TSRMLS_CC); ! 1866: newdateobj->time = timelib_time_ctor(); ! 1867: *newdateobj->time = *it_time; ! 1868: if (it_time->tz_abbr) { ! 1869: newdateobj->time->tz_abbr = strdup(it_time->tz_abbr); ! 1870: } ! 1871: if (it_time->tz_info) { ! 1872: newdateobj->time->tz_info = it_time->tz_info; ! 1873: } ! 1874: ! 1875: *data = &iterator->current; ! 1876: } ! 1877: /* }}} */ ! 1878: ! 1879: ! 1880: /* {{{ date_period_it_current_key */ ! 1881: static int date_period_it_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) ! 1882: { ! 1883: date_period_it *iterator = (date_period_it *)iter; ! 1884: *int_key = iterator->current_index; ! 1885: return HASH_KEY_IS_LONG; ! 1886: } ! 1887: /* }}} */ ! 1888: ! 1889: ! 1890: /* {{{ date_period_it_move_forward */ ! 1891: static void date_period_it_move_forward(zend_object_iterator *iter TSRMLS_DC) ! 1892: { ! 1893: date_period_it *iterator = (date_period_it *)iter; ! 1894: ! 1895: iterator->current_index++; ! 1896: date_period_it_invalidate_current(iter TSRMLS_CC); ! 1897: } ! 1898: /* }}} */ ! 1899: ! 1900: ! 1901: /* {{{ date_period_it_rewind */ ! 1902: static void date_period_it_rewind(zend_object_iterator *iter TSRMLS_DC) ! 1903: { ! 1904: date_period_it *iterator = (date_period_it *)iter; ! 1905: ! 1906: iterator->current_index = 0; ! 1907: if (iterator->object->current) { ! 1908: timelib_time_dtor(iterator->object->current); ! 1909: } ! 1910: iterator->object->current = timelib_time_clone(iterator->object->start); ! 1911: date_period_it_invalidate_current(iter TSRMLS_CC); ! 1912: } ! 1913: /* }}} */ ! 1914: ! 1915: ! 1916: /* iterator handler table */ ! 1917: zend_object_iterator_funcs date_period_it_funcs = { ! 1918: date_period_it_dtor, ! 1919: date_period_it_has_more, ! 1920: date_period_it_current_data, ! 1921: date_period_it_current_key, ! 1922: date_period_it_move_forward, ! 1923: date_period_it_rewind, ! 1924: date_period_it_invalidate_current ! 1925: }; ! 1926: ! 1927: ! 1928: ! 1929: zend_object_iterator *date_object_period_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) ! 1930: { ! 1931: date_period_it *iterator = emalloc(sizeof(date_period_it)); ! 1932: php_period_obj *dpobj = (php_period_obj *)zend_object_store_get_object(object TSRMLS_CC); ! 1933: ! 1934: if (by_ref) { ! 1935: zend_error(E_ERROR, "An iterator cannot be used with foreach by reference"); ! 1936: } ! 1937: ! 1938: Z_ADDREF_P(object); ! 1939: iterator->intern.data = (void*) dpobj; ! 1940: iterator->intern.funcs = &date_period_it_funcs; ! 1941: iterator->date_period_zval = object; ! 1942: iterator->object = dpobj; ! 1943: iterator->current = NULL; ! 1944: ! 1945: return (zend_object_iterator*)iterator; ! 1946: } ! 1947: ! 1948: static void date_register_classes(TSRMLS_D) ! 1949: { ! 1950: zend_class_entry ce_date, ce_timezone, ce_interval, ce_period; ! 1951: ! 1952: INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date); ! 1953: ce_date.create_object = date_object_new_date; ! 1954: date_ce_date = zend_register_internal_class_ex(&ce_date, NULL, NULL TSRMLS_CC); ! 1955: memcpy(&date_object_handlers_date, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); ! 1956: date_object_handlers_date.clone_obj = date_object_clone_date; ! 1957: date_object_handlers_date.compare_objects = date_object_compare_date; ! 1958: date_object_handlers_date.get_properties = date_object_get_properties; ! 1959: ! 1960: #define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \ ! 1961: zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC); ! 1962: ! 1963: REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339); ! 1964: REGISTER_DATE_CLASS_CONST_STRING("COOKIE", DATE_FORMAT_RFC850); ! 1965: REGISTER_DATE_CLASS_CONST_STRING("ISO8601", DATE_FORMAT_ISO8601); ! 1966: REGISTER_DATE_CLASS_CONST_STRING("RFC822", DATE_FORMAT_RFC822); ! 1967: REGISTER_DATE_CLASS_CONST_STRING("RFC850", DATE_FORMAT_RFC850); ! 1968: REGISTER_DATE_CLASS_CONST_STRING("RFC1036", DATE_FORMAT_RFC1036); ! 1969: REGISTER_DATE_CLASS_CONST_STRING("RFC1123", DATE_FORMAT_RFC1123); ! 1970: REGISTER_DATE_CLASS_CONST_STRING("RFC2822", DATE_FORMAT_RFC2822); ! 1971: REGISTER_DATE_CLASS_CONST_STRING("RFC3339", DATE_FORMAT_RFC3339); ! 1972: REGISTER_DATE_CLASS_CONST_STRING("RSS", DATE_FORMAT_RFC1123); ! 1973: REGISTER_DATE_CLASS_CONST_STRING("W3C", DATE_FORMAT_RFC3339); ! 1974: ! 1975: ! 1976: INIT_CLASS_ENTRY(ce_timezone, "DateTimeZone", date_funcs_timezone); ! 1977: ce_timezone.create_object = date_object_new_timezone; ! 1978: date_ce_timezone = zend_register_internal_class_ex(&ce_timezone, NULL, NULL TSRMLS_CC); ! 1979: memcpy(&date_object_handlers_timezone, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); ! 1980: date_object_handlers_timezone.clone_obj = date_object_clone_timezone; ! 1981: ! 1982: #define REGISTER_TIMEZONE_CLASS_CONST_STRING(const_name, value) \ ! 1983: zend_declare_class_constant_long(date_ce_timezone, const_name, sizeof(const_name)-1, value TSRMLS_CC); ! 1984: ! 1985: REGISTER_TIMEZONE_CLASS_CONST_STRING("AFRICA", PHP_DATE_TIMEZONE_GROUP_AFRICA); ! 1986: REGISTER_TIMEZONE_CLASS_CONST_STRING("AMERICA", PHP_DATE_TIMEZONE_GROUP_AMERICA); ! 1987: REGISTER_TIMEZONE_CLASS_CONST_STRING("ANTARCTICA", PHP_DATE_TIMEZONE_GROUP_ANTARCTICA); ! 1988: REGISTER_TIMEZONE_CLASS_CONST_STRING("ARCTIC", PHP_DATE_TIMEZONE_GROUP_ARCTIC); ! 1989: REGISTER_TIMEZONE_CLASS_CONST_STRING("ASIA", PHP_DATE_TIMEZONE_GROUP_ASIA); ! 1990: REGISTER_TIMEZONE_CLASS_CONST_STRING("ATLANTIC", PHP_DATE_TIMEZONE_GROUP_ATLANTIC); ! 1991: REGISTER_TIMEZONE_CLASS_CONST_STRING("AUSTRALIA", PHP_DATE_TIMEZONE_GROUP_AUSTRALIA); ! 1992: REGISTER_TIMEZONE_CLASS_CONST_STRING("EUROPE", PHP_DATE_TIMEZONE_GROUP_EUROPE); ! 1993: REGISTER_TIMEZONE_CLASS_CONST_STRING("INDIAN", PHP_DATE_TIMEZONE_GROUP_INDIAN); ! 1994: REGISTER_TIMEZONE_CLASS_CONST_STRING("PACIFIC", PHP_DATE_TIMEZONE_GROUP_PACIFIC); ! 1995: REGISTER_TIMEZONE_CLASS_CONST_STRING("UTC", PHP_DATE_TIMEZONE_GROUP_UTC); ! 1996: REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL", PHP_DATE_TIMEZONE_GROUP_ALL); ! 1997: REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC", PHP_DATE_TIMEZONE_GROUP_ALL_W_BC); ! 1998: REGISTER_TIMEZONE_CLASS_CONST_STRING("PER_COUNTRY", PHP_DATE_TIMEZONE_PER_COUNTRY); ! 1999: ! 2000: INIT_CLASS_ENTRY(ce_interval, "DateInterval", date_funcs_interval); ! 2001: ce_interval.create_object = date_object_new_interval; ! 2002: date_ce_interval = zend_register_internal_class_ex(&ce_interval, NULL, NULL TSRMLS_CC); ! 2003: memcpy(&date_object_handlers_interval, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); ! 2004: date_object_handlers_interval.clone_obj = date_object_clone_interval; ! 2005: date_object_handlers_interval.read_property = date_interval_read_property; ! 2006: date_object_handlers_interval.write_property = date_interval_write_property; ! 2007: date_object_handlers_interval.get_properties = date_object_get_properties_interval; ! 2008: date_object_handlers_interval.get_property_ptr_ptr = NULL; ! 2009: ! 2010: INIT_CLASS_ENTRY(ce_period, "DatePeriod", date_funcs_period); ! 2011: ce_period.create_object = date_object_new_period; ! 2012: date_ce_period = zend_register_internal_class_ex(&ce_period, NULL, NULL TSRMLS_CC); ! 2013: date_ce_period->get_iterator = date_object_period_get_iterator; ! 2014: date_ce_period->iterator_funcs.funcs = &date_period_it_funcs; ! 2015: zend_class_implements(date_ce_period TSRMLS_CC, 1, zend_ce_traversable); ! 2016: memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); ! 2017: date_object_handlers_period.clone_obj = date_object_clone_period; ! 2018: ! 2019: #define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \ ! 2020: zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value TSRMLS_CC); ! 2021: ! 2022: REGISTER_PERIOD_CLASS_CONST_STRING("EXCLUDE_START_DATE", PHP_DATE_PERIOD_EXCLUDE_START_DATE); ! 2023: } ! 2024: ! 2025: static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_type, php_date_obj **ptr TSRMLS_DC) ! 2026: { ! 2027: php_date_obj *intern; ! 2028: zend_object_value retval; ! 2029: zval *tmp; ! 2030: ! 2031: intern = emalloc(sizeof(php_date_obj)); ! 2032: memset(intern, 0, sizeof(php_date_obj)); ! 2033: if (ptr) { ! 2034: *ptr = intern; ! 2035: } ! 2036: ! 2037: zend_object_std_init(&intern->std, class_type TSRMLS_CC); ! 2038: zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ! 2039: ! 2040: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC); ! 2041: retval.handlers = &date_object_handlers_date; ! 2042: ! 2043: return retval; ! 2044: } ! 2045: ! 2046: static zend_object_value date_object_new_date(zend_class_entry *class_type TSRMLS_DC) ! 2047: { ! 2048: return date_object_new_date_ex(class_type, NULL TSRMLS_CC); ! 2049: } ! 2050: ! 2051: static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC) ! 2052: { ! 2053: php_date_obj *new_obj = NULL; ! 2054: php_date_obj *old_obj = (php_date_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); ! 2055: zend_object_value new_ov = date_object_new_date_ex(old_obj->std.ce, &new_obj TSRMLS_CC); ! 2056: ! 2057: zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); ! 2058: if (!old_obj->time) { ! 2059: return new_ov; ! 2060: } ! 2061: ! 2062: /* this should probably moved to a new `timelib_time *timelime_time_clone(timelib_time *)` */ ! 2063: new_obj->time = timelib_time_ctor(); ! 2064: *new_obj->time = *old_obj->time; ! 2065: if (old_obj->time->tz_abbr) { ! 2066: new_obj->time->tz_abbr = strdup(old_obj->time->tz_abbr); ! 2067: } ! 2068: if (old_obj->time->tz_info) { ! 2069: new_obj->time->tz_info = old_obj->time->tz_info; ! 2070: } ! 2071: ! 2072: return new_ov; ! 2073: } ! 2074: ! 2075: static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC) ! 2076: { ! 2077: if (Z_TYPE_P(d1) == IS_OBJECT && Z_TYPE_P(d2) == IS_OBJECT && ! 2078: instanceof_function(Z_OBJCE_P(d1), date_ce_date TSRMLS_CC) && ! 2079: instanceof_function(Z_OBJCE_P(d2), date_ce_date TSRMLS_CC)) { ! 2080: php_date_obj *o1 = zend_object_store_get_object(d1 TSRMLS_CC); ! 2081: php_date_obj *o2 = zend_object_store_get_object(d2 TSRMLS_CC); ! 2082: ! 2083: if (!o1->time->sse_uptodate) { ! 2084: timelib_update_ts(o1->time, o1->time->tz_info); ! 2085: } ! 2086: if (!o2->time->sse_uptodate) { ! 2087: timelib_update_ts(o2->time, o2->time->tz_info); ! 2088: } ! 2089: ! 2090: return (o1->time->sse == o2->time->sse) ? 0 : ((o1->time->sse < o2->time->sse) ? -1 : 1); ! 2091: } ! 2092: ! 2093: return 1; ! 2094: } ! 2095: ! 2096: static HashTable *date_object_get_properties(zval *object TSRMLS_DC) ! 2097: { ! 2098: HashTable *props; ! 2099: zval *zv; ! 2100: php_date_obj *dateobj; ! 2101: ! 2102: ! 2103: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2104: ! 2105: props = zend_std_get_properties(object TSRMLS_CC); ! 2106: ! 2107: if (!dateobj->time || GC_G(gc_active)) { ! 2108: return props; ! 2109: } ! 2110: ! 2111: /* first we add the date and time in ISO format */ ! 2112: MAKE_STD_ZVAL(zv); ! 2113: ZVAL_STRING(zv, date_format("Y-m-d H:i:s", 12, dateobj->time, 1), 0); ! 2114: zend_hash_update(props, "date", 5, &zv, sizeof(zval), NULL); ! 2115: ! 2116: /* then we add the timezone name (or similar) */ ! 2117: if (dateobj->time->is_localtime) { ! 2118: MAKE_STD_ZVAL(zv); ! 2119: ZVAL_LONG(zv, dateobj->time->zone_type); ! 2120: zend_hash_update(props, "timezone_type", 14, &zv, sizeof(zval), NULL); ! 2121: ! 2122: MAKE_STD_ZVAL(zv); ! 2123: switch (dateobj->time->zone_type) { ! 2124: case TIMELIB_ZONETYPE_ID: ! 2125: ZVAL_STRING(zv, dateobj->time->tz_info->name, 1); ! 2126: break; ! 2127: case TIMELIB_ZONETYPE_OFFSET: { ! 2128: char *tmpstr = emalloc(sizeof("UTC+05:00")); ! 2129: timelib_sll utc_offset = dateobj->time->z; ! 2130: ! 2131: snprintf(tmpstr, sizeof("+05:00"), "%c%02d:%02d", ! 2132: utc_offset > 0 ? '-' : '+', ! 2133: abs(utc_offset / 60), ! 2134: abs((utc_offset % 60))); ! 2135: ! 2136: ZVAL_STRING(zv, tmpstr, 0); ! 2137: } ! 2138: break; ! 2139: case TIMELIB_ZONETYPE_ABBR: ! 2140: ZVAL_STRING(zv, dateobj->time->tz_abbr, 1); ! 2141: break; ! 2142: } ! 2143: zend_hash_update(props, "timezone", 9, &zv, sizeof(zval), NULL); ! 2144: } ! 2145: ! 2146: return props; ! 2147: } ! 2148: ! 2149: static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *class_type, php_timezone_obj **ptr TSRMLS_DC) ! 2150: { ! 2151: php_timezone_obj *intern; ! 2152: zend_object_value retval; ! 2153: zval *tmp; ! 2154: ! 2155: intern = emalloc(sizeof(php_timezone_obj)); ! 2156: memset(intern, 0, sizeof(php_timezone_obj)); ! 2157: if (ptr) { ! 2158: *ptr = intern; ! 2159: } ! 2160: ! 2161: zend_object_std_init(&intern->std, class_type TSRMLS_CC); ! 2162: zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ! 2163: ! 2164: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC); ! 2165: retval.handlers = &date_object_handlers_timezone; ! 2166: ! 2167: return retval; ! 2168: } ! 2169: ! 2170: static zend_object_value date_object_new_timezone(zend_class_entry *class_type TSRMLS_DC) ! 2171: { ! 2172: return date_object_new_timezone_ex(class_type, NULL TSRMLS_CC); ! 2173: } ! 2174: ! 2175: static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC) ! 2176: { ! 2177: php_timezone_obj *new_obj = NULL; ! 2178: php_timezone_obj *old_obj = (php_timezone_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); ! 2179: zend_object_value new_ov = date_object_new_timezone_ex(old_obj->std.ce, &new_obj TSRMLS_CC); ! 2180: ! 2181: zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); ! 2182: if (!old_obj->initialized) { ! 2183: return new_ov; ! 2184: } ! 2185: ! 2186: new_obj->type = old_obj->type; ! 2187: new_obj->initialized = 1; ! 2188: switch (new_obj->type) { ! 2189: case TIMELIB_ZONETYPE_ID: ! 2190: new_obj->tzi.tz = old_obj->tzi.tz; ! 2191: break; ! 2192: case TIMELIB_ZONETYPE_OFFSET: ! 2193: new_obj->tzi.utc_offset = old_obj->tzi.utc_offset; ! 2194: break; ! 2195: case TIMELIB_ZONETYPE_ABBR: ! 2196: new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset; ! 2197: new_obj->tzi.z.dst = old_obj->tzi.z.dst; ! 2198: new_obj->tzi.z.abbr = old_obj->tzi.z.abbr; ! 2199: break; ! 2200: } ! 2201: ! 2202: return new_ov; ! 2203: } ! 2204: ! 2205: static inline zend_object_value date_object_new_interval_ex(zend_class_entry *class_type, php_interval_obj **ptr TSRMLS_DC) ! 2206: { ! 2207: php_interval_obj *intern; ! 2208: zend_object_value retval; ! 2209: zval *tmp; ! 2210: ! 2211: intern = emalloc(sizeof(php_interval_obj)); ! 2212: memset(intern, 0, sizeof(php_interval_obj)); ! 2213: if (ptr) { ! 2214: *ptr = intern; ! 2215: } ! 2216: ! 2217: zend_object_std_init(&intern->std, class_type TSRMLS_CC); ! 2218: zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ! 2219: ! 2220: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC); ! 2221: retval.handlers = &date_object_handlers_interval; ! 2222: ! 2223: return retval; ! 2224: } ! 2225: ! 2226: static zend_object_value date_object_new_interval(zend_class_entry *class_type TSRMLS_DC) ! 2227: { ! 2228: return date_object_new_interval_ex(class_type, NULL TSRMLS_CC); ! 2229: } ! 2230: ! 2231: static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC) ! 2232: { ! 2233: php_interval_obj *new_obj = NULL; ! 2234: php_interval_obj *old_obj = (php_interval_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); ! 2235: zend_object_value new_ov = date_object_new_interval_ex(old_obj->std.ce, &new_obj TSRMLS_CC); ! 2236: ! 2237: zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); ! 2238: ! 2239: /** FIX ME ADD CLONE STUFF **/ ! 2240: return new_ov; ! 2241: } ! 2242: ! 2243: static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) ! 2244: { ! 2245: HashTable *props; ! 2246: zval *zv; ! 2247: php_interval_obj *intervalobj; ! 2248: ! 2249: ! 2250: intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2251: ! 2252: props = zend_std_get_properties(object TSRMLS_CC); ! 2253: ! 2254: if (!intervalobj->initialized || GC_G(gc_active)) { ! 2255: return props; ! 2256: } ! 2257: ! 2258: #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \ ! 2259: MAKE_STD_ZVAL(zv); \ ! 2260: ZVAL_LONG(zv, intervalobj->diff->f); \ ! 2261: zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL); ! 2262: ! 2263: PHP_DATE_INTERVAL_ADD_PROPERTY("y", y); ! 2264: PHP_DATE_INTERVAL_ADD_PROPERTY("m", m); ! 2265: PHP_DATE_INTERVAL_ADD_PROPERTY("d", d); ! 2266: PHP_DATE_INTERVAL_ADD_PROPERTY("h", h); ! 2267: PHP_DATE_INTERVAL_ADD_PROPERTY("i", i); ! 2268: PHP_DATE_INTERVAL_ADD_PROPERTY("s", s); ! 2269: PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert); ! 2270: if (intervalobj->diff->days != -99999) { ! 2271: PHP_DATE_INTERVAL_ADD_PROPERTY("days", days); ! 2272: } else { ! 2273: MAKE_STD_ZVAL(zv); ! 2274: ZVAL_FALSE(zv); ! 2275: zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL); ! 2276: } ! 2277: ! 2278: return props; ! 2279: } ! 2280: ! 2281: static inline zend_object_value date_object_new_period_ex(zend_class_entry *class_type, php_period_obj **ptr TSRMLS_DC) ! 2282: { ! 2283: php_period_obj *intern; ! 2284: zend_object_value retval; ! 2285: zval *tmp; ! 2286: ! 2287: intern = emalloc(sizeof(php_period_obj)); ! 2288: memset(intern, 0, sizeof(php_period_obj)); ! 2289: if (ptr) { ! 2290: *ptr = intern; ! 2291: } ! 2292: ! 2293: zend_object_std_init(&intern->std, class_type TSRMLS_CC); ! 2294: zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); ! 2295: ! 2296: retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC); ! 2297: retval.handlers = &date_object_handlers_period; ! 2298: ! 2299: return retval; ! 2300: } ! 2301: ! 2302: static zend_object_value date_object_new_period(zend_class_entry *class_type TSRMLS_DC) ! 2303: { ! 2304: return date_object_new_period_ex(class_type, NULL TSRMLS_CC); ! 2305: } ! 2306: ! 2307: static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC) ! 2308: { ! 2309: php_period_obj *new_obj = NULL; ! 2310: php_period_obj *old_obj = (php_period_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); ! 2311: zend_object_value new_ov = date_object_new_period_ex(old_obj->std.ce, &new_obj TSRMLS_CC); ! 2312: ! 2313: zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); ! 2314: ! 2315: /** FIX ME ADD CLONE STUFF **/ ! 2316: return new_ov; ! 2317: } ! 2318: ! 2319: static void date_object_free_storage_date(void *object TSRMLS_DC) ! 2320: { ! 2321: php_date_obj *intern = (php_date_obj *)object; ! 2322: ! 2323: if (intern->time) { ! 2324: timelib_time_dtor(intern->time); ! 2325: } ! 2326: ! 2327: zend_object_std_dtor(&intern->std TSRMLS_CC); ! 2328: efree(object); ! 2329: } ! 2330: ! 2331: static void date_object_free_storage_timezone(void *object TSRMLS_DC) ! 2332: { ! 2333: php_timezone_obj *intern = (php_timezone_obj *)object; ! 2334: ! 2335: if (intern->type == TIMELIB_ZONETYPE_ABBR) { ! 2336: free(intern->tzi.z.abbr); ! 2337: } ! 2338: zend_object_std_dtor(&intern->std TSRMLS_CC); ! 2339: efree(object); ! 2340: } ! 2341: ! 2342: static void date_object_free_storage_interval(void *object TSRMLS_DC) ! 2343: { ! 2344: php_interval_obj *intern = (php_interval_obj *)object; ! 2345: ! 2346: timelib_rel_time_dtor(intern->diff); ! 2347: zend_object_std_dtor(&intern->std TSRMLS_CC); ! 2348: efree(object); ! 2349: } ! 2350: ! 2351: static void date_object_free_storage_period(void *object TSRMLS_DC) ! 2352: { ! 2353: php_period_obj *intern = (php_period_obj *)object; ! 2354: ! 2355: if (intern->start) { ! 2356: timelib_time_dtor(intern->start); ! 2357: } ! 2358: ! 2359: if (intern->current) { ! 2360: timelib_time_dtor(intern->current); ! 2361: } ! 2362: ! 2363: if (intern->end) { ! 2364: timelib_time_dtor(intern->end); ! 2365: } ! 2366: ! 2367: timelib_rel_time_dtor(intern->interval); ! 2368: zend_object_std_dtor(&intern->std TSRMLS_CC); ! 2369: efree(object); ! 2370: } ! 2371: ! 2372: /* Advanced Interface */ ! 2373: PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) ! 2374: { ! 2375: Z_TYPE_P(object) = IS_OBJECT; ! 2376: object_init_ex(object, pce); ! 2377: Z_SET_REFCOUNT_P(object, 1); ! 2378: Z_UNSET_ISREF_P(object); ! 2379: return object; ! 2380: } ! 2381: ! 2382: /* Helper function used to store the latest found warnings and errors while ! 2383: * parsing, from either strtotime or parse_from_format. */ ! 2384: static void update_errors_warnings(timelib_error_container *last_errors TSRMLS_DC) ! 2385: { ! 2386: if (DATEG(last_errors)) { ! 2387: timelib_error_container_dtor(DATEG(last_errors)); ! 2388: DATEG(last_errors) = NULL; ! 2389: } ! 2390: DATEG(last_errors) = last_errors; ! 2391: } ! 2392: ! 2393: PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, int time_str_len, char *format, zval *timezone_object, int ctor TSRMLS_DC) ! 2394: { ! 2395: timelib_time *now; ! 2396: timelib_tzinfo *tzi = NULL; ! 2397: timelib_error_container *err = NULL; ! 2398: int type = TIMELIB_ZONETYPE_ID, new_dst; ! 2399: char *new_abbr; ! 2400: timelib_sll new_offset; ! 2401: ! 2402: if (dateobj->time) { ! 2403: timelib_time_dtor(dateobj->time); ! 2404: } ! 2405: if (format) { ! 2406: dateobj->time = timelib_parse_from_format(format, time_str_len ? time_str : "", time_str_len ? time_str_len : 0, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 2407: } else { ! 2408: dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 2409: } ! 2410: ! 2411: /* update last errors and warnings */ ! 2412: update_errors_warnings(err TSRMLS_CC); ! 2413: ! 2414: ! 2415: if (ctor && err && err->error_count) { ! 2416: /* spit out the first library error message, at least */ ! 2417: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", time_str, ! 2418: err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message); ! 2419: } ! 2420: if (err && err->error_count) { ! 2421: return 0; ! 2422: } ! 2423: ! 2424: if (timezone_object) { ! 2425: php_timezone_obj *tzobj; ! 2426: ! 2427: tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); ! 2428: switch (tzobj->type) { ! 2429: case TIMELIB_ZONETYPE_ID: ! 2430: tzi = tzobj->tzi.tz; ! 2431: break; ! 2432: case TIMELIB_ZONETYPE_OFFSET: ! 2433: new_offset = tzobj->tzi.utc_offset; ! 2434: break; ! 2435: case TIMELIB_ZONETYPE_ABBR: ! 2436: new_offset = tzobj->tzi.z.utc_offset; ! 2437: new_dst = tzobj->tzi.z.dst; ! 2438: new_abbr = strdup(tzobj->tzi.z.abbr); ! 2439: break; ! 2440: } ! 2441: type = tzobj->type; ! 2442: } else if (dateobj->time->tz_info) { ! 2443: tzi = dateobj->time->tz_info; ! 2444: } else { ! 2445: tzi = get_timezone_info(TSRMLS_C); ! 2446: } ! 2447: ! 2448: now = timelib_time_ctor(); ! 2449: now->zone_type = type; ! 2450: switch (type) { ! 2451: case TIMELIB_ZONETYPE_ID: ! 2452: now->tz_info = tzi; ! 2453: break; ! 2454: case TIMELIB_ZONETYPE_OFFSET: ! 2455: now->z = new_offset; ! 2456: break; ! 2457: case TIMELIB_ZONETYPE_ABBR: ! 2458: now->z = new_offset; ! 2459: now->dst = new_dst; ! 2460: now->tz_abbr = new_abbr; ! 2461: break; ! 2462: } ! 2463: timelib_unixtime2local(now, (timelib_sll) time(NULL)); ! 2464: ! 2465: timelib_fill_holes(dateobj->time, now, TIMELIB_NO_CLONE); ! 2466: timelib_update_ts(dateobj->time, tzi); ! 2467: ! 2468: dateobj->time->have_relative = 0; ! 2469: ! 2470: timelib_time_dtor(now); ! 2471: ! 2472: return 1; ! 2473: } ! 2474: ! 2475: /* {{{ proto DateTime date_create([string time[, DateTimeZone object]]) ! 2476: Returns new DateTime object ! 2477: */ ! 2478: PHP_FUNCTION(date_create) ! 2479: { ! 2480: zval *timezone_object = NULL; ! 2481: char *time_str = NULL; ! 2482: int time_str_len = 0; ! 2483: ! 2484: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) { ! 2485: RETURN_FALSE; ! 2486: } ! 2487: ! 2488: php_date_instantiate(date_ce_date, return_value TSRMLS_CC); ! 2489: if (!php_date_initialize(zend_object_store_get_object(return_value TSRMLS_CC), time_str, time_str_len, NULL, timezone_object, 0 TSRMLS_CC)) { ! 2490: RETURN_FALSE; ! 2491: } ! 2492: } ! 2493: /* }}} */ ! 2494: ! 2495: /* {{{ proto DateTime date_create_from_format(string format, string time[, DateTimeZone object]) ! 2496: Returns new DateTime object formatted according to the specified format ! 2497: */ ! 2498: PHP_FUNCTION(date_create_from_format) ! 2499: { ! 2500: zval *timezone_object = NULL; ! 2501: char *time_str = NULL, *format_str = NULL; ! 2502: int time_str_len = 0, format_str_len = 0; ! 2503: ! 2504: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|O", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) { ! 2505: RETURN_FALSE; ! 2506: } ! 2507: ! 2508: php_date_instantiate(date_ce_date, return_value TSRMLS_CC); ! 2509: if (!php_date_initialize(zend_object_store_get_object(return_value TSRMLS_CC), time_str, time_str_len, format_str, timezone_object, 0 TSRMLS_CC)) { ! 2510: RETURN_FALSE; ! 2511: } ! 2512: } ! 2513: /* }}} */ ! 2514: ! 2515: /* {{{ proto DateTime::__construct([string time[, DateTimeZone object]]) ! 2516: Creates new DateTime object ! 2517: */ ! 2518: PHP_METHOD(DateTime, __construct) ! 2519: { ! 2520: zval *timezone_object = NULL; ! 2521: char *time_str = NULL; ! 2522: int time_str_len = 0; ! 2523: zend_error_handling error_handling; ! 2524: ! 2525: zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); ! 2526: if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) { ! 2527: php_date_initialize(zend_object_store_get_object(getThis() TSRMLS_CC), time_str, time_str_len, NULL, timezone_object, 1 TSRMLS_CC); ! 2528: } ! 2529: zend_restore_error_handling(&error_handling TSRMLS_CC); ! 2530: } ! 2531: /* }}} */ ! 2532: ! 2533: static int php_date_initialize_from_hash(zval **return_value, php_date_obj **dateobj, HashTable *myht TSRMLS_DC) ! 2534: { ! 2535: zval **z_date = NULL; ! 2536: zval **z_timezone = NULL; ! 2537: zval **z_timezone_type = NULL; ! 2538: zval *tmp_obj = NULL; ! 2539: timelib_tzinfo *tzi; ! 2540: php_timezone_obj *tzobj; ! 2541: ! 2542: if (zend_hash_find(myht, "date", 5, (void**) &z_date) == SUCCESS) { ! 2543: convert_to_string(*z_date); ! 2544: if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) { ! 2545: convert_to_long(*z_timezone_type); ! 2546: if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) { ! 2547: convert_to_string(*z_timezone); ! 2548: ! 2549: switch (Z_LVAL_PP(z_timezone_type)) { ! 2550: case TIMELIB_ZONETYPE_OFFSET: ! 2551: case TIMELIB_ZONETYPE_ABBR: { ! 2552: char *tmp = emalloc(Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2); ! 2553: snprintf(tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 2, "%s %s", Z_STRVAL_PP(z_date), Z_STRVAL_PP(z_timezone)); ! 2554: php_date_initialize(*dateobj, tmp, Z_STRLEN_PP(z_date) + Z_STRLEN_PP(z_timezone) + 1, NULL, NULL, 0 TSRMLS_CC); ! 2555: efree(tmp); ! 2556: return 1; ! 2557: } ! 2558: ! 2559: case TIMELIB_ZONETYPE_ID: ! 2560: convert_to_string(*z_timezone); ! 2561: ! 2562: tzi = php_date_parse_tzfile(Z_STRVAL_PP(z_timezone), DATE_TIMEZONEDB TSRMLS_CC); ! 2563: ! 2564: ALLOC_INIT_ZVAL(tmp_obj); ! 2565: tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, tmp_obj TSRMLS_CC) TSRMLS_CC); ! 2566: tzobj->type = TIMELIB_ZONETYPE_ID; ! 2567: tzobj->tzi.tz = tzi; ! 2568: tzobj->initialized = 1; ! 2569: ! 2570: php_date_initialize(*dateobj, Z_STRVAL_PP(z_date), Z_STRLEN_PP(z_date), NULL, tmp_obj, 0 TSRMLS_CC); ! 2571: zval_ptr_dtor(&tmp_obj); ! 2572: return 1; ! 2573: } ! 2574: } ! 2575: } ! 2576: } ! 2577: return 0; ! 2578: } ! 2579: ! 2580: /* {{{ proto DateTime::__set_state() ! 2581: */ ! 2582: PHP_METHOD(DateTime, __set_state) ! 2583: { ! 2584: php_date_obj *dateobj; ! 2585: zval *array; ! 2586: HashTable *myht; ! 2587: ! 2588: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { ! 2589: RETURN_FALSE; ! 2590: } ! 2591: ! 2592: myht = HASH_OF(array); ! 2593: ! 2594: php_date_instantiate(date_ce_date, return_value TSRMLS_CC); ! 2595: dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC); ! 2596: php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); ! 2597: } ! 2598: /* }}} */ ! 2599: ! 2600: /* {{{ proto DateTime::__wakeup() ! 2601: */ ! 2602: PHP_METHOD(DateTime, __wakeup) ! 2603: { ! 2604: zval *object = getThis(); ! 2605: php_date_obj *dateobj; ! 2606: HashTable *myht; ! 2607: ! 2608: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2609: ! 2610: myht = Z_OBJPROP_P(object); ! 2611: ! 2612: php_date_initialize_from_hash(&return_value, &dateobj, myht TSRMLS_CC); ! 2613: } ! 2614: /* }}} */ ! 2615: ! 2616: /* Helper function used to add an associative array of warnings and errors to a zval */ ! 2617: static void zval_from_error_container(zval *z, timelib_error_container *error) ! 2618: { ! 2619: int i; ! 2620: zval *element; ! 2621: ! 2622: add_assoc_long(z, "warning_count", error->warning_count); ! 2623: MAKE_STD_ZVAL(element); ! 2624: array_init(element); ! 2625: for (i = 0; i < error->warning_count; i++) { ! 2626: add_index_string(element, error->warning_messages[i].position, error->warning_messages[i].message, 1); ! 2627: } ! 2628: add_assoc_zval(z, "warnings", element); ! 2629: ! 2630: add_assoc_long(z, "error_count", error->error_count); ! 2631: MAKE_STD_ZVAL(element); ! 2632: array_init(element); ! 2633: for (i = 0; i < error->error_count; i++) { ! 2634: add_index_string(element, error->error_messages[i].position, error->error_messages[i].message, 1); ! 2635: } ! 2636: add_assoc_zval(z, "errors", element); ! 2637: } ! 2638: ! 2639: /* {{{ proto array date_get_last_errors() ! 2640: Returns the warnings and errors found while parsing a date/time string. ! 2641: */ ! 2642: PHP_FUNCTION(date_get_last_errors) ! 2643: { ! 2644: if (DATEG(last_errors)) { ! 2645: array_init(return_value); ! 2646: zval_from_error_container(return_value, DATEG(last_errors)); ! 2647: } else { ! 2648: RETURN_FALSE; ! 2649: } ! 2650: } ! 2651: /* }}} */ ! 2652: ! 2653: void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time *parsed_time, struct timelib_error_container *error) ! 2654: { ! 2655: zval *element; ! 2656: ! 2657: array_init(return_value); ! 2658: #define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem) \ ! 2659: if (parsed_time->elem == -99999) { \ ! 2660: add_assoc_bool(return_value, #name, 0); \ ! 2661: } else { \ ! 2662: add_assoc_long(return_value, #name, parsed_time->elem); \ ! 2663: } ! 2664: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(year, y); ! 2665: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(month, m); ! 2666: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(day, d); ! 2667: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(hour, h); ! 2668: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(minute, i); ! 2669: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(second, s); ! 2670: ! 2671: if (parsed_time->f == -99999) { ! 2672: add_assoc_bool(return_value, "fraction", 0); ! 2673: } else { ! 2674: add_assoc_double(return_value, "fraction", parsed_time->f); ! 2675: } ! 2676: ! 2677: zval_from_error_container(return_value, error); ! 2678: ! 2679: timelib_error_container_dtor(error); ! 2680: ! 2681: add_assoc_bool(return_value, "is_localtime", parsed_time->is_localtime); ! 2682: ! 2683: if (parsed_time->is_localtime) { ! 2684: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone_type, zone_type); ! 2685: switch (parsed_time->zone_type) { ! 2686: case TIMELIB_ZONETYPE_OFFSET: ! 2687: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z); ! 2688: add_assoc_bool(return_value, "is_dst", parsed_time->dst); ! 2689: break; ! 2690: case TIMELIB_ZONETYPE_ID: ! 2691: if (parsed_time->tz_abbr) { ! 2692: add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr, 1); ! 2693: } ! 2694: if (parsed_time->tz_info) { ! 2695: add_assoc_string(return_value, "tz_id", parsed_time->tz_info->name, 1); ! 2696: } ! 2697: break; ! 2698: case TIMELIB_ZONETYPE_ABBR: ! 2699: PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z); ! 2700: add_assoc_bool(return_value, "is_dst", parsed_time->dst); ! 2701: add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr, 1); ! 2702: break; ! 2703: } ! 2704: } ! 2705: if (parsed_time->have_relative) { ! 2706: MAKE_STD_ZVAL(element); ! 2707: array_init(element); ! 2708: add_assoc_long(element, "year", parsed_time->relative.y); ! 2709: add_assoc_long(element, "month", parsed_time->relative.m); ! 2710: add_assoc_long(element, "day", parsed_time->relative.d); ! 2711: add_assoc_long(element, "hour", parsed_time->relative.h); ! 2712: add_assoc_long(element, "minute", parsed_time->relative.i); ! 2713: add_assoc_long(element, "second", parsed_time->relative.s); ! 2714: if (parsed_time->relative.have_weekday_relative) { ! 2715: add_assoc_long(element, "weekday", parsed_time->relative.weekday); ! 2716: } ! 2717: if (parsed_time->relative.have_special_relative && (parsed_time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY)) { ! 2718: add_assoc_long(element, "weekdays", parsed_time->relative.special.amount); ! 2719: } ! 2720: if (parsed_time->relative.first_last_day_of) { ! 2721: add_assoc_bool(element, parsed_time->relative.first_last_day_of == 1 ? "first_day_of_month" : "last_day_of_month", 1); ! 2722: } ! 2723: add_assoc_zval(return_value, "relative", element); ! 2724: } ! 2725: timelib_time_dtor(parsed_time); ! 2726: } ! 2727: ! 2728: /* {{{ proto array date_parse(string date) ! 2729: Returns associative array with detailed info about given date ! 2730: */ ! 2731: PHP_FUNCTION(date_parse) ! 2732: { ! 2733: char *date; ! 2734: int date_len; ! 2735: struct timelib_error_container *error; ! 2736: timelib_time *parsed_time; ! 2737: ! 2738: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &date, &date_len) == FAILURE) { ! 2739: RETURN_FALSE; ! 2740: } ! 2741: ! 2742: parsed_time = timelib_strtotime(date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 2743: php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error); ! 2744: } ! 2745: /* }}} */ ! 2746: ! 2747: /* {{{ proto array date_parse_from_format(string format, string date) ! 2748: Returns associative array with detailed info about given date ! 2749: */ ! 2750: PHP_FUNCTION(date_parse_from_format) ! 2751: { ! 2752: char *date, *format; ! 2753: int date_len, format_len; ! 2754: struct timelib_error_container *error; ! 2755: timelib_time *parsed_time; ! 2756: ! 2757: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &format, &format_len, &date, &date_len) == FAILURE) { ! 2758: RETURN_FALSE; ! 2759: } ! 2760: ! 2761: parsed_time = timelib_parse_from_format(format, date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 2762: php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error); ! 2763: } ! 2764: /* }}} */ ! 2765: ! 2766: /* {{{ proto string date_format(DateTime object, string format) ! 2767: Returns date formatted according to given format ! 2768: */ ! 2769: PHP_FUNCTION(date_format) ! 2770: { ! 2771: zval *object; ! 2772: php_date_obj *dateobj; ! 2773: char *format; ! 2774: int format_len; ! 2775: ! 2776: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, date_ce_date, &format, &format_len) == FAILURE) { ! 2777: RETURN_FALSE; ! 2778: } ! 2779: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2780: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2781: RETURN_STRING(date_format(format, format_len, dateobj->time, dateobj->time->is_localtime), 0); ! 2782: } ! 2783: /* }}} */ ! 2784: ! 2785: /* {{{ proto DateTime date_modify(DateTime object, string modify) ! 2786: Alters the timestamp. ! 2787: */ ! 2788: PHP_FUNCTION(date_modify) ! 2789: { ! 2790: zval *object; ! 2791: php_date_obj *dateobj; ! 2792: char *modify; ! 2793: int modify_len; ! 2794: timelib_time *tmp_time; ! 2795: timelib_error_container *err = NULL; ! 2796: ! 2797: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, date_ce_date, &modify, &modify_len) == FAILURE) { ! 2798: RETURN_FALSE; ! 2799: } ! 2800: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2801: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2802: ! 2803: tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 2804: ! 2805: /* update last errors and warnings */ ! 2806: update_errors_warnings(err TSRMLS_CC); ! 2807: if (err && err->error_count) { ! 2808: /* spit out the first library error message, at least */ ! 2809: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse time string (%s) at position %d (%c): %s", modify, ! 2810: err->error_messages[0].position, err->error_messages[0].character, err->error_messages[0].message); ! 2811: timelib_time_dtor(tmp_time); ! 2812: RETURN_FALSE; ! 2813: } ! 2814: ! 2815: memcpy(&dateobj->time->relative, &tmp_time->relative, sizeof(struct timelib_rel_time)); ! 2816: dateobj->time->have_relative = tmp_time->have_relative; ! 2817: dateobj->time->sse_uptodate = 0; ! 2818: ! 2819: if (tmp_time->y != -99999) { ! 2820: dateobj->time->y = tmp_time->y; ! 2821: } ! 2822: if (tmp_time->m != -99999) { ! 2823: dateobj->time->m = tmp_time->m; ! 2824: } ! 2825: if (tmp_time->d != -99999) { ! 2826: dateobj->time->d = tmp_time->d; ! 2827: } ! 2828: ! 2829: if (tmp_time->h != -99999) { ! 2830: dateobj->time->h = tmp_time->h; ! 2831: if (tmp_time->i != -99999) { ! 2832: dateobj->time->i = tmp_time->i; ! 2833: if (tmp_time->s != -99999) { ! 2834: dateobj->time->s = tmp_time->s; ! 2835: } else { ! 2836: dateobj->time->s = 0; ! 2837: } ! 2838: } else { ! 2839: dateobj->time->i = 0; ! 2840: dateobj->time->s = 0; ! 2841: } ! 2842: } ! 2843: timelib_time_dtor(tmp_time); ! 2844: ! 2845: timelib_update_ts(dateobj->time, NULL); ! 2846: timelib_update_from_sse(dateobj->time); ! 2847: dateobj->time->have_relative = 0; ! 2848: ! 2849: RETURN_ZVAL(object, 1, 0); ! 2850: } ! 2851: /* }}} */ ! 2852: ! 2853: /* {{{ proto DateTime date_add(DateTime object, DateInterval interval) ! 2854: Adds an interval to the current date in object. ! 2855: */ ! 2856: PHP_FUNCTION(date_add) ! 2857: { ! 2858: zval *object, *interval; ! 2859: php_date_obj *dateobj; ! 2860: php_interval_obj *intobj; ! 2861: int bias = 1; ! 2862: ! 2863: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) { ! 2864: RETURN_FALSE; ! 2865: } ! 2866: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2867: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2868: intobj = (php_interval_obj *) zend_object_store_get_object(interval TSRMLS_CC); ! 2869: DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval); ! 2870: ! 2871: ! 2872: if (intobj->diff->have_weekday_relative || intobj->diff->have_special_relative) { ! 2873: memcpy(&dateobj->time->relative, intobj->diff, sizeof(struct timelib_rel_time)); ! 2874: } else { ! 2875: if (intobj->diff->invert) { ! 2876: bias = -1; ! 2877: } ! 2878: memset(&dateobj->time->relative, 0, sizeof(struct timelib_rel_time)); ! 2879: dateobj->time->relative.y = intobj->diff->y * bias; ! 2880: dateobj->time->relative.m = intobj->diff->m * bias; ! 2881: dateobj->time->relative.d = intobj->diff->d * bias; ! 2882: dateobj->time->relative.h = intobj->diff->h * bias; ! 2883: dateobj->time->relative.i = intobj->diff->i * bias; ! 2884: dateobj->time->relative.s = intobj->diff->s * bias; ! 2885: } ! 2886: dateobj->time->have_relative = 1; ! 2887: dateobj->time->sse_uptodate = 0; ! 2888: ! 2889: timelib_update_ts(dateobj->time, NULL); ! 2890: timelib_update_from_sse(dateobj->time); ! 2891: dateobj->time->have_relative = 0; ! 2892: ! 2893: RETURN_ZVAL(object, 1, 0); ! 2894: } ! 2895: /* }}} */ ! 2896: ! 2897: /* {{{ proto DateTime date_sub(DateTime object, DateInterval interval) ! 2898: Subtracts an interval to the current date in object. ! 2899: */ ! 2900: PHP_FUNCTION(date_sub) ! 2901: { ! 2902: zval *object, *interval; ! 2903: php_date_obj *dateobj; ! 2904: php_interval_obj *intobj; ! 2905: int bias = 1; ! 2906: ! 2907: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_date, &interval, date_ce_interval) == FAILURE) { ! 2908: RETURN_FALSE; ! 2909: } ! 2910: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2911: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2912: intobj = (php_interval_obj *) zend_object_store_get_object(interval TSRMLS_CC); ! 2913: DATE_CHECK_INITIALIZED(intobj->initialized, DateInterval); ! 2914: ! 2915: if (intobj->diff->have_special_relative) { ! 2916: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only non-special relative time specifications are supported for subtraction"); ! 2917: return; ! 2918: } ! 2919: ! 2920: if (intobj->diff->invert) { ! 2921: bias = -1; ! 2922: } ! 2923: ! 2924: memset(&dateobj->time->relative, 0, sizeof(struct timelib_rel_time)); ! 2925: dateobj->time->relative.y = 0 - (intobj->diff->y * bias); ! 2926: dateobj->time->relative.m = 0 - (intobj->diff->m * bias); ! 2927: dateobj->time->relative.d = 0 - (intobj->diff->d * bias); ! 2928: dateobj->time->relative.h = 0 - (intobj->diff->h * bias); ! 2929: dateobj->time->relative.i = 0 - (intobj->diff->i * bias); ! 2930: dateobj->time->relative.s = 0 - (intobj->diff->s * bias); ! 2931: dateobj->time->have_relative = 1; ! 2932: dateobj->time->sse_uptodate = 0; ! 2933: ! 2934: timelib_update_ts(dateobj->time, NULL); ! 2935: timelib_update_from_sse(dateobj->time); ! 2936: ! 2937: dateobj->time->have_relative = 0; ! 2938: ! 2939: RETURN_ZVAL(object, 1, 0); ! 2940: } ! 2941: /* }}} */ ! 2942: ! 2943: /* {{{ proto DateTimeZone date_timezone_get(DateTime object) ! 2944: Return new DateTimeZone object relative to give DateTime ! 2945: */ ! 2946: PHP_FUNCTION(date_timezone_get) ! 2947: { ! 2948: zval *object; ! 2949: php_date_obj *dateobj; ! 2950: php_timezone_obj *tzobj; ! 2951: ! 2952: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_date) == FAILURE) { ! 2953: RETURN_FALSE; ! 2954: } ! 2955: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2956: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2957: if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) { ! 2958: php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC); ! 2959: tzobj = (php_timezone_obj *) zend_object_store_get_object(return_value TSRMLS_CC); ! 2960: tzobj->initialized = 1; ! 2961: tzobj->type = dateobj->time->zone_type; ! 2962: switch (dateobj->time->zone_type) { ! 2963: case TIMELIB_ZONETYPE_ID: ! 2964: tzobj->tzi.tz = dateobj->time->tz_info; ! 2965: break; ! 2966: case TIMELIB_ZONETYPE_OFFSET: ! 2967: tzobj->tzi.utc_offset = dateobj->time->z; ! 2968: break; ! 2969: case TIMELIB_ZONETYPE_ABBR: ! 2970: tzobj->tzi.z.utc_offset = dateobj->time->z; ! 2971: tzobj->tzi.z.dst = dateobj->time->dst; ! 2972: tzobj->tzi.z.abbr = strdup(dateobj->time->tz_abbr); ! 2973: break; ! 2974: } ! 2975: } else { ! 2976: RETURN_FALSE; ! 2977: } ! 2978: } ! 2979: /* }}} */ ! 2980: ! 2981: /* {{{ proto DateTime date_timezone_set(DateTime object, DateTimeZone object) ! 2982: Sets the timezone for the DateTime object. ! 2983: */ ! 2984: PHP_FUNCTION(date_timezone_set) ! 2985: { ! 2986: zval *object; ! 2987: zval *timezone_object; ! 2988: php_date_obj *dateobj; ! 2989: php_timezone_obj *tzobj; ! 2990: ! 2991: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_date, &timezone_object, date_ce_timezone) == FAILURE) { ! 2992: RETURN_FALSE; ! 2993: } ! 2994: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 2995: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 2996: tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); ! 2997: if (tzobj->type != TIMELIB_ZONETYPE_ID) { ! 2998: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only do this for zones with ID for now"); ! 2999: return; ! 3000: } ! 3001: timelib_set_timezone(dateobj->time, tzobj->tzi.tz); ! 3002: timelib_unixtime2local(dateobj->time, dateobj->time->sse); ! 3003: ! 3004: RETURN_ZVAL(object, 1, 0); ! 3005: } ! 3006: /* }}} */ ! 3007: ! 3008: /* {{{ proto long date_offset_get(DateTime object) ! 3009: Returns the DST offset. ! 3010: */ ! 3011: PHP_FUNCTION(date_offset_get) ! 3012: { ! 3013: zval *object; ! 3014: php_date_obj *dateobj; ! 3015: timelib_time_offset *offset; ! 3016: ! 3017: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_date) == FAILURE) { ! 3018: RETURN_FALSE; ! 3019: } ! 3020: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3021: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3022: if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) { ! 3023: switch (dateobj->time->zone_type) { ! 3024: case TIMELIB_ZONETYPE_ID: ! 3025: offset = timelib_get_time_zone_info(dateobj->time->sse, dateobj->time->tz_info); ! 3026: RETVAL_LONG(offset->offset); ! 3027: timelib_time_offset_dtor(offset); ! 3028: break; ! 3029: case TIMELIB_ZONETYPE_OFFSET: ! 3030: RETVAL_LONG(dateobj->time->z * -60); ! 3031: break; ! 3032: case TIMELIB_ZONETYPE_ABBR: ! 3033: RETVAL_LONG((dateobj->time->z - (60 * dateobj->time->dst)) * -60); ! 3034: break; ! 3035: } ! 3036: return; ! 3037: } else { ! 3038: RETURN_LONG(0); ! 3039: } ! 3040: } ! 3041: /* }}} */ ! 3042: ! 3043: /* {{{ proto DateTime date_time_set(DateTime object, long hour, long minute[, long second]) ! 3044: Sets the time. ! 3045: */ ! 3046: PHP_FUNCTION(date_time_set) ! 3047: { ! 3048: zval *object; ! 3049: php_date_obj *dateobj; ! 3050: long h, i, s = 0; ! 3051: ! 3052: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll|l", &object, date_ce_date, &h, &i, &s) == FAILURE) { ! 3053: RETURN_FALSE; ! 3054: } ! 3055: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3056: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3057: dateobj->time->h = h; ! 3058: dateobj->time->i = i; ! 3059: dateobj->time->s = s; ! 3060: timelib_update_ts(dateobj->time, NULL); ! 3061: ! 3062: RETURN_ZVAL(object, 1, 0); ! 3063: } ! 3064: /* }}} */ ! 3065: ! 3066: /* {{{ proto DateTime date_date_set(DateTime object, long year, long month, long day) ! 3067: Sets the date. ! 3068: */ ! 3069: PHP_FUNCTION(date_date_set) ! 3070: { ! 3071: zval *object; ! 3072: php_date_obj *dateobj; ! 3073: long y, m, d; ! 3074: ! 3075: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olll", &object, date_ce_date, &y, &m, &d) == FAILURE) { ! 3076: RETURN_FALSE; ! 3077: } ! 3078: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3079: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3080: dateobj->time->y = y; ! 3081: dateobj->time->m = m; ! 3082: dateobj->time->d = d; ! 3083: timelib_update_ts(dateobj->time, NULL); ! 3084: ! 3085: RETURN_ZVAL(object, 1, 0); ! 3086: } ! 3087: /* }}} */ ! 3088: ! 3089: /* {{{ proto DateTime date_isodate_set(DateTime object, long year, long week[, long day]) ! 3090: Sets the ISO date. ! 3091: */ ! 3092: PHP_FUNCTION(date_isodate_set) ! 3093: { ! 3094: zval *object; ! 3095: php_date_obj *dateobj; ! 3096: long y, w, d = 1; ! 3097: ! 3098: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll|l", &object, date_ce_date, &y, &w, &d) == FAILURE) { ! 3099: RETURN_FALSE; ! 3100: } ! 3101: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3102: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3103: dateobj->time->y = y; ! 3104: dateobj->time->m = 1; ! 3105: dateobj->time->d = 1; ! 3106: memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative)); ! 3107: dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d); ! 3108: dateobj->time->have_relative = 1; ! 3109: ! 3110: timelib_update_ts(dateobj->time, NULL); ! 3111: ! 3112: RETURN_ZVAL(object, 1, 0); ! 3113: } ! 3114: /* }}} */ ! 3115: ! 3116: /* {{{ proto DateTime date_timestamp_set(DateTime object, long unixTimestamp) ! 3117: Sets the date and time based on an Unix timestamp. ! 3118: */ ! 3119: PHP_FUNCTION(date_timestamp_set) ! 3120: { ! 3121: zval *object; ! 3122: php_date_obj *dateobj; ! 3123: long timestamp; ! 3124: ! 3125: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &object, date_ce_date, ×tamp) == FAILURE) { ! 3126: RETURN_FALSE; ! 3127: } ! 3128: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3129: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3130: timelib_unixtime2local(dateobj->time, (timelib_sll)timestamp); ! 3131: timelib_update_ts(dateobj->time, NULL); ! 3132: ! 3133: RETURN_ZVAL(object, 1, 0); ! 3134: } ! 3135: /* }}} */ ! 3136: ! 3137: /* {{{ proto long date_timestamp_get(DateTime object) ! 3138: Gets the Unix timestamp. ! 3139: */ ! 3140: PHP_FUNCTION(date_timestamp_get) ! 3141: { ! 3142: zval *object; ! 3143: php_date_obj *dateobj; ! 3144: long timestamp; ! 3145: int error; ! 3146: ! 3147: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_date) == FAILURE) { ! 3148: RETURN_FALSE; ! 3149: } ! 3150: dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3151: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3152: timelib_update_ts(dateobj->time, NULL); ! 3153: ! 3154: timestamp = timelib_date_to_int(dateobj->time, &error); ! 3155: if (error) { ! 3156: RETURN_FALSE; ! 3157: } else { ! 3158: RETVAL_LONG(timestamp); ! 3159: } ! 3160: } ! 3161: /* }}} */ ! 3162: ! 3163: /* {{{ proto DateInterval date_diff(DateTime object [, bool absolute]) ! 3164: Returns the difference between two DateTime objects. ! 3165: */ ! 3166: PHP_FUNCTION(date_diff) ! 3167: { ! 3168: zval *object1, *object2; ! 3169: php_date_obj *dateobj1, *dateobj2; ! 3170: php_interval_obj *interval; ! 3171: long absolute = 0; ! 3172: ! 3173: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO|l", &object1, date_ce_date, &object2, date_ce_date, &absolute) == FAILURE) { ! 3174: RETURN_FALSE; ! 3175: } ! 3176: dateobj1 = (php_date_obj *) zend_object_store_get_object(object1 TSRMLS_CC); ! 3177: dateobj2 = (php_date_obj *) zend_object_store_get_object(object2 TSRMLS_CC); ! 3178: DATE_CHECK_INITIALIZED(dateobj1->time, DateTime); ! 3179: DATE_CHECK_INITIALIZED(dateobj2->time, DateTime); ! 3180: timelib_update_ts(dateobj1->time, NULL); ! 3181: timelib_update_ts(dateobj2->time, NULL); ! 3182: ! 3183: php_date_instantiate(date_ce_interval, return_value TSRMLS_CC); ! 3184: interval = zend_object_store_get_object(return_value TSRMLS_CC); ! 3185: interval->diff = timelib_diff(dateobj1->time, dateobj2->time); ! 3186: if (absolute) { ! 3187: interval->diff->invert = 0; ! 3188: } ! 3189: interval->initialized = 1; ! 3190: } ! 3191: /* }}} */ ! 3192: ! 3193: static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz TSRMLS_DC) ! 3194: { ! 3195: char *tzid; ! 3196: ! 3197: *tzi = NULL; ! 3198: ! 3199: if ((tzid = timelib_timezone_id_from_abbr(tz, -1, 0))) { ! 3200: *tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC); ! 3201: } else { ! 3202: *tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC); ! 3203: } ! 3204: ! 3205: if (*tzi) { ! 3206: return SUCCESS; ! 3207: } else { ! 3208: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad timezone (%s)", tz); ! 3209: return FAILURE; ! 3210: } ! 3211: } ! 3212: ! 3213: /* {{{ proto DateTimeZone timezone_open(string timezone) ! 3214: Returns new DateTimeZone object ! 3215: */ ! 3216: PHP_FUNCTION(timezone_open) ! 3217: { ! 3218: char *tz; ! 3219: int tz_len; ! 3220: timelib_tzinfo *tzi = NULL; ! 3221: php_timezone_obj *tzobj; ! 3222: ! 3223: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len) == FAILURE) { ! 3224: RETURN_FALSE; ! 3225: } ! 3226: if (SUCCESS != timezone_initialize(&tzi, tz TSRMLS_CC)) { ! 3227: RETURN_FALSE; ! 3228: } ! 3229: tzobj = zend_object_store_get_object(php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC); ! 3230: tzobj->type = TIMELIB_ZONETYPE_ID; ! 3231: tzobj->tzi.tz = tzi; ! 3232: tzobj->initialized = 1; ! 3233: } ! 3234: /* }}} */ ! 3235: ! 3236: /* {{{ proto DateTimeZone::__construct(string timezone) ! 3237: Creates new DateTimeZone object. ! 3238: */ ! 3239: PHP_METHOD(DateTimeZone, __construct) ! 3240: { ! 3241: char *tz; ! 3242: int tz_len; ! 3243: timelib_tzinfo *tzi = NULL; ! 3244: php_timezone_obj *tzobj; ! 3245: zend_error_handling error_handling; ! 3246: ! 3247: zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); ! 3248: if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) { ! 3249: if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) { ! 3250: tzobj = zend_object_store_get_object(getThis() TSRMLS_CC); ! 3251: tzobj->type = TIMELIB_ZONETYPE_ID; ! 3252: tzobj->tzi.tz = tzi; ! 3253: tzobj->initialized = 1; ! 3254: } else { ! 3255: ZVAL_NULL(getThis()); ! 3256: } ! 3257: } ! 3258: zend_restore_error_handling(&error_handling TSRMLS_CC); ! 3259: } ! 3260: /* }}} */ ! 3261: ! 3262: /* {{{ proto string timezone_name_get(DateTimeZone object) ! 3263: Returns the name of the timezone. ! 3264: */ ! 3265: PHP_FUNCTION(timezone_name_get) ! 3266: { ! 3267: zval *object; ! 3268: php_timezone_obj *tzobj; ! 3269: ! 3270: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_timezone) == FAILURE) { ! 3271: RETURN_FALSE; ! 3272: } ! 3273: tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3274: DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone); ! 3275: ! 3276: switch (tzobj->type) { ! 3277: case TIMELIB_ZONETYPE_ID: ! 3278: RETURN_STRING(tzobj->tzi.tz->name, 1); ! 3279: break; ! 3280: case TIMELIB_ZONETYPE_OFFSET: { ! 3281: char *tmpstr = emalloc(sizeof("UTC+05:00")); ! 3282: timelib_sll utc_offset = tzobj->tzi.utc_offset; ! 3283: ! 3284: snprintf(tmpstr, sizeof("+05:00"), "%c%02d:%02d", ! 3285: utc_offset > 0 ? '-' : '+', ! 3286: abs(utc_offset / 60), ! 3287: abs((utc_offset % 60))); ! 3288: ! 3289: RETURN_STRING(tmpstr, 0); ! 3290: } ! 3291: break; ! 3292: case TIMELIB_ZONETYPE_ABBR: ! 3293: RETURN_STRING(tzobj->tzi.z.abbr, 1); ! 3294: break; ! 3295: } ! 3296: } ! 3297: /* }}} */ ! 3298: ! 3299: /* {{{ proto string timezone_name_from_abbr(string abbr[, long gmtOffset[, long isdst]]) ! 3300: Returns the timezone name from abbrevation ! 3301: */ ! 3302: PHP_FUNCTION(timezone_name_from_abbr) ! 3303: { ! 3304: char *abbr; ! 3305: char *tzid; ! 3306: int abbr_len; ! 3307: long gmtoffset = -1; ! 3308: long isdst = -1; ! 3309: ! 3310: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &abbr, &abbr_len, &gmtoffset, &isdst) == FAILURE) { ! 3311: RETURN_FALSE; ! 3312: } ! 3313: tzid = timelib_timezone_id_from_abbr(abbr, gmtoffset, isdst); ! 3314: ! 3315: if (tzid) { ! 3316: RETURN_STRING(tzid, 1); ! 3317: } else { ! 3318: RETURN_FALSE; ! 3319: } ! 3320: } ! 3321: /* }}} */ ! 3322: ! 3323: /* {{{ proto long timezone_offset_get(DateTimeZone object, DateTime object) ! 3324: Returns the timezone offset. ! 3325: */ ! 3326: PHP_FUNCTION(timezone_offset_get) ! 3327: { ! 3328: zval *object, *dateobject; ! 3329: php_timezone_obj *tzobj; ! 3330: php_date_obj *dateobj; ! 3331: timelib_time_offset *offset; ! 3332: ! 3333: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &object, date_ce_timezone, &dateobject, date_ce_date) == FAILURE) { ! 3334: RETURN_FALSE; ! 3335: } ! 3336: tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3337: DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone); ! 3338: dateobj = (php_date_obj *) zend_object_store_get_object(dateobject TSRMLS_CC); ! 3339: DATE_CHECK_INITIALIZED(dateobj->time, DateTime); ! 3340: ! 3341: switch (tzobj->type) { ! 3342: case TIMELIB_ZONETYPE_ID: ! 3343: offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tzi.tz); ! 3344: RETVAL_LONG(offset->offset); ! 3345: timelib_time_offset_dtor(offset); ! 3346: break; ! 3347: case TIMELIB_ZONETYPE_OFFSET: ! 3348: RETURN_LONG(tzobj->tzi.utc_offset * -60); ! 3349: break; ! 3350: case TIMELIB_ZONETYPE_ABBR: ! 3351: RETURN_LONG((tzobj->tzi.z.utc_offset - (tzobj->tzi.z.dst*60)) * -60); ! 3352: break; ! 3353: } ! 3354: } ! 3355: /* }}} */ ! 3356: ! 3357: /* {{{ proto array timezone_transitions_get(DateTimeZone object [, long timestamp_begin [, long timestamp_end ]]) ! 3358: Returns numerically indexed array containing associative array for all transitions in the specified range for the timezone. ! 3359: */ ! 3360: PHP_FUNCTION(timezone_transitions_get) ! 3361: { ! 3362: zval *object, *element; ! 3363: php_timezone_obj *tzobj; ! 3364: unsigned int i, begin = 0, found; ! 3365: long timestamp_begin = LONG_MIN, timestamp_end = LONG_MAX; ! 3366: ! 3367: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|ll", &object, date_ce_timezone, ×tamp_begin, ×tamp_end) == FAILURE) { ! 3368: RETURN_FALSE; ! 3369: } ! 3370: tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3371: DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone); ! 3372: if (tzobj->type != TIMELIB_ZONETYPE_ID) { ! 3373: RETURN_FALSE; ! 3374: } ! 3375: ! 3376: #define add_nominal() \ ! 3377: MAKE_STD_ZVAL(element); \ ! 3378: array_init(element); \ ! 3379: add_assoc_long(element, "ts", timestamp_begin); \ ! 3380: add_assoc_string(element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, timestamp_begin, 0 TSRMLS_CC), 0); \ ! 3381: add_assoc_long(element, "offset", tzobj->tzi.tz->type[0].offset); \ ! 3382: add_assoc_bool(element, "isdst", tzobj->tzi.tz->type[0].isdst); \ ! 3383: add_assoc_string(element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[0].abbr_idx], 1); \ ! 3384: add_next_index_zval(return_value, element); ! 3385: ! 3386: #define add(i,ts) \ ! 3387: MAKE_STD_ZVAL(element); \ ! 3388: array_init(element); \ ! 3389: add_assoc_long(element, "ts", ts); \ ! 3390: add_assoc_string(element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, ts, 0 TSRMLS_CC), 0); \ ! 3391: add_assoc_long(element, "offset", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].offset); \ ! 3392: add_assoc_bool(element, "isdst", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].isdst); \ ! 3393: add_assoc_string(element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].abbr_idx], 1); \ ! 3394: add_next_index_zval(return_value, element); ! 3395: ! 3396: #define add_last() add(tzobj->tzi.tz->timecnt - 1, timestamp_begin) ! 3397: ! 3398: array_init(return_value); ! 3399: ! 3400: if (timestamp_begin == LONG_MIN) { ! 3401: add_nominal(); ! 3402: begin = 0; ! 3403: found = 1; ! 3404: } else { ! 3405: begin = 0; ! 3406: found = 0; ! 3407: if (tzobj->tzi.tz->timecnt > 0) { ! 3408: do { ! 3409: if (tzobj->tzi.tz->trans[begin] > timestamp_begin) { ! 3410: if (begin > 0) { ! 3411: add(begin - 1, timestamp_begin); ! 3412: } else { ! 3413: add_nominal(); ! 3414: } ! 3415: found = 1; ! 3416: break; ! 3417: } ! 3418: begin++; ! 3419: } while (begin < tzobj->tzi.tz->timecnt); ! 3420: } ! 3421: } ! 3422: ! 3423: if (!found) { ! 3424: if (tzobj->tzi.tz->timecnt > 0) { ! 3425: add_last(); ! 3426: } else { ! 3427: add_nominal(); ! 3428: } ! 3429: } else { ! 3430: for (i = begin; i < tzobj->tzi.tz->timecnt; ++i) { ! 3431: if (tzobj->tzi.tz->trans[i] < timestamp_end) { ! 3432: add(i, tzobj->tzi.tz->trans[i]); ! 3433: } ! 3434: } ! 3435: } ! 3436: } ! 3437: /* }}} */ ! 3438: ! 3439: /* {{{ proto array timezone_location_get() ! 3440: Returns location information for a timezone, including country code, latitude/longitude and comments ! 3441: */ ! 3442: PHP_FUNCTION(timezone_location_get) ! 3443: { ! 3444: zval *object; ! 3445: php_timezone_obj *tzobj; ! 3446: ! 3447: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_timezone) == FAILURE) { ! 3448: RETURN_FALSE; ! 3449: } ! 3450: tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3451: DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone); ! 3452: if (tzobj->type != TIMELIB_ZONETYPE_ID) { ! 3453: RETURN_FALSE; ! 3454: } ! 3455: ! 3456: array_init(return_value); ! 3457: add_assoc_string(return_value, "country_code", tzobj->tzi.tz->location.country_code, 1); ! 3458: add_assoc_double(return_value, "latitude", tzobj->tzi.tz->location.latitude); ! 3459: add_assoc_double(return_value, "longitude", tzobj->tzi.tz->location.longitude); ! 3460: add_assoc_string(return_value, "comments", tzobj->tzi.tz->location.comments, 1); ! 3461: } ! 3462: /* }}} */ ! 3463: ! 3464: static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *format, int format_length TSRMLS_DC) ! 3465: { ! 3466: timelib_time *b = NULL, *e = NULL; ! 3467: timelib_rel_time *p = NULL; ! 3468: int r = 0; ! 3469: int retval = 0; ! 3470: struct timelib_error_container *errors; ! 3471: ! 3472: timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); ! 3473: ! 3474: if (errors->error_count > 0) { ! 3475: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); ! 3476: retval = FAILURE; ! 3477: } else { ! 3478: if(p) { ! 3479: *rt = p; ! 3480: retval = SUCCESS; ! 3481: } else { ! 3482: if(b && e) { ! 3483: timelib_update_ts(b, NULL); ! 3484: timelib_update_ts(e, NULL); ! 3485: *rt = timelib_diff(b, e); ! 3486: retval = SUCCESS; ! 3487: } else { ! 3488: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse interval (%s)", format); ! 3489: retval = FAILURE; ! 3490: } ! 3491: } ! 3492: } ! 3493: timelib_error_container_dtor(errors); ! 3494: return retval; ! 3495: } ! 3496: ! 3497: /* {{{ date_interval_read_property */ ! 3498: zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC) ! 3499: { ! 3500: php_interval_obj *obj; ! 3501: zval *retval; ! 3502: zval tmp_member; ! 3503: timelib_sll value = -1; ! 3504: ! 3505: if (member->type != IS_STRING) { ! 3506: tmp_member = *member; ! 3507: zval_copy_ctor(&tmp_member); ! 3508: convert_to_string(&tmp_member); ! 3509: member = &tmp_member; ! 3510: } ! 3511: ! 3512: obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC); ! 3513: ! 3514: #define GET_VALUE_FROM_STRUCT(n,m) \ ! 3515: if (strcmp(Z_STRVAL_P(member), m) == 0) { \ ! 3516: value = obj->diff->n; \ ! 3517: break; \ ! 3518: } ! 3519: do { ! 3520: GET_VALUE_FROM_STRUCT(y, "y"); ! 3521: GET_VALUE_FROM_STRUCT(m, "m"); ! 3522: GET_VALUE_FROM_STRUCT(d, "d"); ! 3523: GET_VALUE_FROM_STRUCT(h, "h"); ! 3524: GET_VALUE_FROM_STRUCT(i, "i"); ! 3525: GET_VALUE_FROM_STRUCT(s, "s"); ! 3526: GET_VALUE_FROM_STRUCT(invert, "invert"); ! 3527: GET_VALUE_FROM_STRUCT(days, "days"); ! 3528: /* didn't find any */ ! 3529: retval = (zend_get_std_object_handlers())->read_property(object, member, type TSRMLS_CC); ! 3530: ! 3531: if (member == &tmp_member) { ! 3532: zval_dtor(member); ! 3533: } ! 3534: ! 3535: return retval; ! 3536: } while(0); ! 3537: ! 3538: ALLOC_INIT_ZVAL(retval); ! 3539: Z_SET_REFCOUNT_P(retval, 0); ! 3540: ! 3541: ZVAL_LONG(retval, value); ! 3542: ! 3543: if (member == &tmp_member) { ! 3544: zval_dtor(member); ! 3545: } ! 3546: ! 3547: return retval; ! 3548: } ! 3549: /* }}} */ ! 3550: ! 3551: /* {{{ date_interval_write_property */ ! 3552: void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC) ! 3553: { ! 3554: php_interval_obj *obj; ! 3555: zval tmp_member, tmp_value; ! 3556: ! 3557: if (member->type != IS_STRING) { ! 3558: tmp_member = *member; ! 3559: zval_copy_ctor(&tmp_member); ! 3560: convert_to_string(&tmp_member); ! 3561: member = &tmp_member; ! 3562: } ! 3563: obj = (php_interval_obj *)zend_objects_get_address(object TSRMLS_CC); ! 3564: ! 3565: #define SET_VALUE_FROM_STRUCT(n,m) \ ! 3566: if (strcmp(Z_STRVAL_P(member), m) == 0) { \ ! 3567: if (value->type != IS_LONG) { \ ! 3568: tmp_value = *value; \ ! 3569: zval_copy_ctor(&tmp_value); \ ! 3570: convert_to_long(&tmp_value); \ ! 3571: value = &tmp_value; \ ! 3572: } \ ! 3573: obj->diff->n = Z_LVAL_P(value); \ ! 3574: if (value == &tmp_value) { \ ! 3575: zval_dtor(value); \ ! 3576: } \ ! 3577: break; \ ! 3578: } ! 3579: ! 3580: do { ! 3581: SET_VALUE_FROM_STRUCT(y, "y"); ! 3582: SET_VALUE_FROM_STRUCT(m, "m"); ! 3583: SET_VALUE_FROM_STRUCT(d, "d"); ! 3584: SET_VALUE_FROM_STRUCT(h, "h"); ! 3585: SET_VALUE_FROM_STRUCT(i, "i"); ! 3586: SET_VALUE_FROM_STRUCT(s, "s"); ! 3587: SET_VALUE_FROM_STRUCT(invert, "invert"); ! 3588: /* didn't find any */ ! 3589: (zend_get_std_object_handlers())->write_property(object, member, value TSRMLS_CC); ! 3590: } while(0); ! 3591: ! 3592: if (member == &tmp_member) { ! 3593: zval_dtor(member); ! 3594: } ! 3595: } ! 3596: /* }}} */ ! 3597: ! 3598: ! 3599: /* {{{ proto DateInterval::__construct([string interval_spec]) ! 3600: Creates new DateInterval object. ! 3601: */ ! 3602: PHP_METHOD(DateInterval, __construct) ! 3603: { ! 3604: char *interval_string = NULL; ! 3605: int interval_string_length; ! 3606: php_interval_obj *diobj; ! 3607: timelib_rel_time *reltime; ! 3608: zend_error_handling error_handling; ! 3609: ! 3610: zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); ! 3611: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &interval_string, &interval_string_length) == SUCCESS) { ! 3612: if (date_interval_initialize(&reltime, interval_string, interval_string_length TSRMLS_CC) == SUCCESS) { ! 3613: diobj = zend_object_store_get_object(getThis() TSRMLS_CC); ! 3614: diobj->diff = reltime; ! 3615: diobj->initialized = 1; ! 3616: } else { ! 3617: ZVAL_NULL(getThis()); ! 3618: } ! 3619: } ! 3620: zend_restore_error_handling(&error_handling TSRMLS_CC); ! 3621: } ! 3622: /* }}} */ ! 3623: ! 3624: static long php_date_long_from_hash_element(HashTable *myht, char *element, size_t size) ! 3625: { ! 3626: zval **z_arg = NULL; ! 3627: ! 3628: if (zend_hash_find(myht, element, size + 1, (void**) &z_arg) == SUCCESS) { ! 3629: convert_to_long(*z_arg); ! 3630: return Z_LVAL_PP(z_arg); ! 3631: } else { ! 3632: return -1; ! 3633: } ! 3634: } ! 3635: ! 3636: static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC) ! 3637: { ! 3638: (*intobj)->diff = timelib_rel_time_ctor(); ! 3639: ! 3640: (*intobj)->diff->y = php_date_long_from_hash_element(myht, "y", 1); ! 3641: (*intobj)->diff->m = php_date_long_from_hash_element(myht, "m", 1); ! 3642: (*intobj)->diff->d = php_date_long_from_hash_element(myht, "d", 1); ! 3643: (*intobj)->diff->h = php_date_long_from_hash_element(myht, "h", 1); ! 3644: (*intobj)->diff->i = php_date_long_from_hash_element(myht, "i", 1); ! 3645: (*intobj)->diff->s = php_date_long_from_hash_element(myht, "s", 1); ! 3646: (*intobj)->diff->invert = php_date_long_from_hash_element(myht, "invert", 6); ! 3647: (*intobj)->diff->days = php_date_long_from_hash_element(myht, "days", 4); ! 3648: (*intobj)->initialized = 1; ! 3649: ! 3650: return 0; ! 3651: } ! 3652: ! 3653: /* {{{ proto DateInterval::__set_state() ! 3654: */ ! 3655: PHP_METHOD(DateInterval, __set_state) ! 3656: { ! 3657: php_interval_obj *intobj; ! 3658: zval *array; ! 3659: HashTable *myht; ! 3660: ! 3661: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { ! 3662: RETURN_FALSE; ! 3663: } ! 3664: ! 3665: myht = HASH_OF(array); ! 3666: ! 3667: php_date_instantiate(date_ce_interval, return_value TSRMLS_CC); ! 3668: intobj = (php_interval_obj *) zend_object_store_get_object(return_value TSRMLS_CC); ! 3669: php_date_interval_initialize_from_hash(&return_value, &intobj, myht TSRMLS_CC); ! 3670: } ! 3671: /* }}} */ ! 3672: ! 3673: /* {{{ proto DateInterval::__wakeup() ! 3674: */ ! 3675: PHP_METHOD(DateInterval, __wakeup) ! 3676: { ! 3677: zval *object = getThis(); ! 3678: php_interval_obj *intobj; ! 3679: HashTable *myht; ! 3680: ! 3681: intobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3682: ! 3683: myht = Z_OBJPROP_P(object); ! 3684: ! 3685: php_date_interval_initialize_from_hash(&return_value, &intobj, myht TSRMLS_CC); ! 3686: } ! 3687: /* }}} */ ! 3688: /* {{{ proto DateInterval date_interval_create_from_date_string(string time) ! 3689: Uses the normal date parsers and sets up a DateInterval from the relative parts of the parsed string ! 3690: */ ! 3691: PHP_FUNCTION(date_interval_create_from_date_string) ! 3692: { ! 3693: char *time_str = NULL; ! 3694: int time_str_len = 0; ! 3695: timelib_time *time; ! 3696: timelib_error_container *err = NULL; ! 3697: php_interval_obj *diobj; ! 3698: ! 3699: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &time_str, &time_str_len) == FAILURE) { ! 3700: RETURN_FALSE; ! 3701: } ! 3702: ! 3703: php_date_instantiate(date_ce_interval, return_value TSRMLS_CC); ! 3704: ! 3705: time = timelib_strtotime(time_str, time_str_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); ! 3706: diobj = (php_interval_obj *) zend_object_store_get_object(return_value TSRMLS_CC); ! 3707: diobj->diff = timelib_rel_time_clone(&time->relative); ! 3708: diobj->initialized = 1; ! 3709: timelib_time_dtor(time); ! 3710: timelib_error_container_dtor(err); ! 3711: } ! 3712: /* }}} */ ! 3713: ! 3714: /* {{{ date_interval_format - */ ! 3715: static char *date_interval_format(char *format, int format_len, timelib_rel_time *t) ! 3716: { ! 3717: smart_str string = {0}; ! 3718: int i, length, have_format_spec = 0; ! 3719: char buffer[33]; ! 3720: ! 3721: if (!format_len) { ! 3722: return estrdup(""); ! 3723: } ! 3724: ! 3725: for (i = 0; i < format_len; i++) { ! 3726: if (have_format_spec) { ! 3727: switch (format[i]) { ! 3728: case 'Y': length = slprintf(buffer, 32, "%02d", (int) t->y); break; ! 3729: case 'y': length = slprintf(buffer, 32, "%d", (int) t->y); break; ! 3730: ! 3731: case 'M': length = slprintf(buffer, 32, "%02d", (int) t->m); break; ! 3732: case 'm': length = slprintf(buffer, 32, "%d", (int) t->m); break; ! 3733: ! 3734: case 'D': length = slprintf(buffer, 32, "%02d", (int) t->d); break; ! 3735: case 'd': length = slprintf(buffer, 32, "%d", (int) t->d); break; ! 3736: ! 3737: case 'H': length = slprintf(buffer, 32, "%02d", (int) t->h); break; ! 3738: case 'h': length = slprintf(buffer, 32, "%d", (int) t->h); break; ! 3739: ! 3740: case 'I': length = slprintf(buffer, 32, "%02d", (int) t->i); break; ! 3741: case 'i': length = slprintf(buffer, 32, "%d", (int) t->i); break; ! 3742: ! 3743: case 'S': length = slprintf(buffer, 32, "%02ld", (long) t->s); break; ! 3744: case 's': length = slprintf(buffer, 32, "%ld", (long) t->s); break; ! 3745: ! 3746: case 'a': { ! 3747: if ((int) t->days != -99999) { ! 3748: length = slprintf(buffer, 32, "%d", (int) t->days); ! 3749: } else { ! 3750: length = slprintf(buffer, 32, "(unknown)"); ! 3751: } ! 3752: } break; ! 3753: case 'r': length = slprintf(buffer, 32, "%s", t->invert ? "-" : ""); break; ! 3754: case 'R': length = slprintf(buffer, 32, "%c", t->invert ? '-' : '+'); break; ! 3755: ! 3756: case '%': length = slprintf(buffer, 32, "%%"); break; ! 3757: default: buffer[0] = '%'; buffer[1] = format[i]; buffer[2] = '\0'; length = 2; break; ! 3758: } ! 3759: smart_str_appendl(&string, buffer, length); ! 3760: have_format_spec = 0; ! 3761: } else { ! 3762: if (format[i] == '%') { ! 3763: have_format_spec = 1; ! 3764: } else { ! 3765: smart_str_appendc(&string, format[i]); ! 3766: } ! 3767: } ! 3768: } ! 3769: ! 3770: smart_str_0(&string); ! 3771: ! 3772: return string.c; ! 3773: } ! 3774: /* }}} */ ! 3775: ! 3776: /* {{{ proto string date_interval_format(DateInterval object, string format) ! 3777: Formats the interval. ! 3778: */ ! 3779: PHP_FUNCTION(date_interval_format) ! 3780: { ! 3781: zval *object; ! 3782: php_interval_obj *diobj; ! 3783: char *format; ! 3784: int format_len; ! 3785: ! 3786: if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, date_ce_interval, &format, &format_len) == FAILURE) { ! 3787: RETURN_FALSE; ! 3788: } ! 3789: diobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); ! 3790: DATE_CHECK_INITIALIZED(diobj->initialized, DateInterval); ! 3791: ! 3792: RETURN_STRING(date_interval_format(format, format_len, diobj->diff), 0); ! 3793: } ! 3794: /* }}} */ ! 3795: ! 3796: static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_rel_time **d, long *recurrences, /*const*/ char *format, int format_length TSRMLS_DC) ! 3797: { ! 3798: timelib_time *b = NULL, *e = NULL; ! 3799: timelib_rel_time *p = NULL; ! 3800: int r = 0; ! 3801: int retval = 0; ! 3802: struct timelib_error_container *errors; ! 3803: ! 3804: timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); ! 3805: ! 3806: if (errors->error_count > 0) { ! 3807: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); ! 3808: retval = FAILURE; ! 3809: } else { ! 3810: *st = b; ! 3811: *et = e; ! 3812: *d = p; ! 3813: *recurrences = r; ! 3814: retval = SUCCESS; ! 3815: } ! 3816: timelib_error_container_dtor(errors); ! 3817: return retval; ! 3818: } ! 3819: ! 3820: /* {{{ proto DatePeriod::__construct(DateTime $start, DateInterval $interval, int recurrences|DateTime $end) ! 3821: Creates new DatePeriod object. ! 3822: */ ! 3823: PHP_METHOD(DatePeriod, __construct) ! 3824: { ! 3825: php_period_obj *dpobj; ! 3826: php_date_obj *dateobj; ! 3827: php_interval_obj *intobj; ! 3828: zval *start, *end = NULL, *interval; ! 3829: long recurrences = 0, options = 0; ! 3830: char *isostr = NULL; ! 3831: int isostr_len = 0; ! 3832: timelib_time *clone; ! 3833: zend_error_handling error_handling; ! 3834: ! 3835: zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); ! 3836: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOl|l", &start, date_ce_date, &interval, date_ce_interval, &recurrences, &options) == FAILURE) { ! 3837: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOO|l", &start, date_ce_date, &interval, date_ce_interval, &end, date_ce_date, &options) == FAILURE) { ! 3838: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &isostr, &isostr_len, &options) == FAILURE) { ! 3839: php_error_docref(NULL TSRMLS_CC, E_WARNING, "This constructor accepts either (DateTime, DateInterval, int) OR (DateTime, DateInterval, DateTime) OR (string) as arguments."); ! 3840: zend_restore_error_handling(&error_handling TSRMLS_CC); ! 3841: return; ! 3842: } ! 3843: } ! 3844: } ! 3845: ! 3846: dpobj = zend_object_store_get_object(getThis() TSRMLS_CC); ! 3847: dpobj->current = NULL; ! 3848: ! 3849: if (isostr) { ! 3850: date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), &recurrences, isostr, isostr_len TSRMLS_CC); ! 3851: if (dpobj->start == NULL) { ! 3852: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ISO interval '%s' did not contain a start date.", isostr); ! 3853: } ! 3854: if (dpobj->interval == NULL) { ! 3855: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ISO interval '%s' did not contain an interval.", isostr); ! 3856: } ! 3857: if (dpobj->end == NULL && recurrences == 0) { ! 3858: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The ISO interval '%s' did not contain an end date or a recurrence count.", isostr); ! 3859: } ! 3860: ! 3861: if (dpobj->start) { ! 3862: timelib_update_ts(dpobj->start, NULL); ! 3863: } ! 3864: if (dpobj->end) { ! 3865: timelib_update_ts(dpobj->end, NULL); ! 3866: } ! 3867: } else { ! 3868: /* init */ ! 3869: intobj = (php_interval_obj *) zend_object_store_get_object(interval TSRMLS_CC); ! 3870: ! 3871: /* start date */ ! 3872: dateobj = (php_date_obj *) zend_object_store_get_object(start TSRMLS_CC); ! 3873: clone = timelib_time_ctor(); ! 3874: memcpy(clone, dateobj->time, sizeof(timelib_time)); ! 3875: if (dateobj->time->tz_abbr) { ! 3876: clone->tz_abbr = strdup(dateobj->time->tz_abbr); ! 3877: } ! 3878: if (dateobj->time->tz_info) { ! 3879: clone->tz_info = dateobj->time->tz_info; ! 3880: } ! 3881: dpobj->start = clone; ! 3882: ! 3883: /* interval */ ! 3884: dpobj->interval = timelib_rel_time_clone(intobj->diff); ! 3885: ! 3886: /* end date */ ! 3887: if (end) { ! 3888: dateobj = (php_date_obj *) zend_object_store_get_object(end TSRMLS_CC); ! 3889: clone = timelib_time_clone(dateobj->time); ! 3890: dpobj->end = clone; ! 3891: } ! 3892: } ! 3893: ! 3894: /* options */ ! 3895: dpobj->include_start_date = !(options & PHP_DATE_PERIOD_EXCLUDE_START_DATE); ! 3896: ! 3897: /* recurrrences */ ! 3898: dpobj->recurrences = recurrences + dpobj->include_start_date; ! 3899: ! 3900: dpobj->initialized = 1; ! 3901: ! 3902: zend_restore_error_handling(&error_handling TSRMLS_CC); ! 3903: } ! 3904: /* }}} */ ! 3905: ! 3906: static int check_id_allowed(char *id, long what) ! 3907: { ! 3908: if (what & PHP_DATE_TIMEZONE_GROUP_AFRICA && strncasecmp(id, "Africa/", 7) == 0) return 1; ! 3909: if (what & PHP_DATE_TIMEZONE_GROUP_AMERICA && strncasecmp(id, "America/", 8) == 0) return 1; ! 3910: if (what & PHP_DATE_TIMEZONE_GROUP_ANTARCTICA && strncasecmp(id, "Antarctica/", 11) == 0) return 1; ! 3911: if (what & PHP_DATE_TIMEZONE_GROUP_ARCTIC && strncasecmp(id, "Arctic/", 7) == 0) return 1; ! 3912: if (what & PHP_DATE_TIMEZONE_GROUP_ASIA && strncasecmp(id, "Asia/", 5) == 0) return 1; ! 3913: if (what & PHP_DATE_TIMEZONE_GROUP_ATLANTIC && strncasecmp(id, "Atlantic/", 9) == 0) return 1; ! 3914: if (what & PHP_DATE_TIMEZONE_GROUP_AUSTRALIA && strncasecmp(id, "Australia/", 10) == 0) return 1; ! 3915: if (what & PHP_DATE_TIMEZONE_GROUP_EUROPE && strncasecmp(id, "Europe/", 7) == 0) return 1; ! 3916: if (what & PHP_DATE_TIMEZONE_GROUP_INDIAN && strncasecmp(id, "Indian/", 7) == 0) return 1; ! 3917: if (what & PHP_DATE_TIMEZONE_GROUP_PACIFIC && strncasecmp(id, "Pacific/", 8) == 0) return 1; ! 3918: if (what & PHP_DATE_TIMEZONE_GROUP_UTC && strncasecmp(id, "UTC", 3) == 0) return 1; ! 3919: return 0; ! 3920: } ! 3921: ! 3922: /* {{{ proto array timezone_identifiers_list([long what[, string country]]) ! 3923: Returns numerically index array with all timezone identifiers. ! 3924: */ ! 3925: PHP_FUNCTION(timezone_identifiers_list) ! 3926: { ! 3927: const timelib_tzdb *tzdb; ! 3928: const timelib_tzdb_index_entry *table; ! 3929: int i, item_count; ! 3930: long what = PHP_DATE_TIMEZONE_GROUP_ALL; ! 3931: char *option = NULL; ! 3932: int option_len = 0; ! 3933: ! 3934: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &what, &option, &option_len) == FAILURE) { ! 3935: RETURN_FALSE; ! 3936: } ! 3937: ! 3938: /* Extra validation */ ! 3939: if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) { ! 3940: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "A two-letter ISO 3166-1 compatible country code is expected"); ! 3941: RETURN_FALSE; ! 3942: } ! 3943: ! 3944: tzdb = DATE_TIMEZONEDB; ! 3945: item_count = tzdb->index_size; ! 3946: table = tzdb->index; ! 3947: ! 3948: array_init(return_value); ! 3949: ! 3950: for (i = 0; i < item_count; ++i) { ! 3951: if (what == PHP_DATE_TIMEZONE_PER_COUNTRY) { ! 3952: if (tzdb->data[table[i].pos + 5] == option[0] && tzdb->data[table[i].pos + 6] == option[1]) { ! 3953: add_next_index_string(return_value, table[i].id, 1); ! 3954: } ! 3955: } else if (what == PHP_DATE_TIMEZONE_GROUP_ALL_W_BC || (check_id_allowed(table[i].id, what) && (tzdb->data[table[i].pos + 4] == '\1'))) { ! 3956: add_next_index_string(return_value, table[i].id, 1); ! 3957: } ! 3958: }; ! 3959: } ! 3960: /* }}} */ ! 3961: ! 3962: /* {{{ proto array timezone_version_get() ! 3963: Returns the Olson database version number. ! 3964: */ ! 3965: PHP_FUNCTION(timezone_version_get) ! 3966: { ! 3967: const timelib_tzdb *tzdb; ! 3968: ! 3969: tzdb = DATE_TIMEZONEDB; ! 3970: RETURN_STRING(tzdb->version, 1); ! 3971: } ! 3972: /* }}} */ ! 3973: ! 3974: /* {{{ proto array timezone_abbreviations_list() ! 3975: Returns associative array containing dst, offset and the timezone name ! 3976: */ ! 3977: PHP_FUNCTION(timezone_abbreviations_list) ! 3978: { ! 3979: const timelib_tz_lookup_table *table, *entry; ! 3980: zval *element, **abbr_array_pp, *abbr_array; ! 3981: ! 3982: table = timelib_timezone_abbreviations_list(); ! 3983: array_init(return_value); ! 3984: entry = table; ! 3985: ! 3986: do { ! 3987: MAKE_STD_ZVAL(element); ! 3988: array_init(element); ! 3989: add_assoc_bool(element, "dst", entry->type); ! 3990: add_assoc_long(element, "offset", entry->gmtoffset); ! 3991: if (entry->full_tz_name) { ! 3992: add_assoc_string(element, "timezone_id", entry->full_tz_name, 1); ! 3993: } else { ! 3994: add_assoc_null(element, "timezone_id"); ! 3995: } ! 3996: ! 3997: if (zend_hash_find(HASH_OF(return_value), entry->name, strlen(entry->name) + 1, (void **) &abbr_array_pp) == FAILURE) { ! 3998: MAKE_STD_ZVAL(abbr_array); ! 3999: array_init(abbr_array); ! 4000: add_assoc_zval(return_value, entry->name, abbr_array); ! 4001: } else { ! 4002: abbr_array = *abbr_array_pp; ! 4003: } ! 4004: add_next_index_zval(abbr_array, element); ! 4005: entry++; ! 4006: } while (entry->name); ! 4007: } ! 4008: /* }}} */ ! 4009: ! 4010: /* {{{ proto bool date_default_timezone_set(string timezone_identifier) ! 4011: Sets the default timezone used by all date/time functions in a script */ ! 4012: PHP_FUNCTION(date_default_timezone_set) ! 4013: { ! 4014: char *zone; ! 4015: int zone_len; ! 4016: ! 4017: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &zone, &zone_len) == FAILURE) { ! 4018: RETURN_FALSE; ! 4019: } ! 4020: if (!timelib_timezone_id_is_valid(zone, DATE_TIMEZONEDB)) { ! 4021: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Timezone ID '%s' is invalid", zone); ! 4022: RETURN_FALSE; ! 4023: } ! 4024: if (DATEG(timezone)) { ! 4025: efree(DATEG(timezone)); ! 4026: DATEG(timezone) = NULL; ! 4027: } ! 4028: DATEG(timezone) = estrndup(zone, zone_len); ! 4029: RETURN_TRUE; ! 4030: } ! 4031: /* }}} */ ! 4032: ! 4033: /* {{{ proto string date_default_timezone_get() ! 4034: Gets the default timezone used by all date/time functions in a script */ ! 4035: PHP_FUNCTION(date_default_timezone_get) ! 4036: { ! 4037: timelib_tzinfo *default_tz; ! 4038: ! 4039: default_tz = get_timezone_info(TSRMLS_C); ! 4040: RETVAL_STRING(default_tz->name, 1); ! 4041: } ! 4042: /* }}} */ ! 4043: ! 4044: /* {{{ php_do_date_sunrise_sunset ! 4045: * Common for date_sunrise() and date_sunset() functions ! 4046: */ ! 4047: static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_sunset) ! 4048: { ! 4049: double latitude = 0.0, longitude = 0.0, zenith = 0.0, gmt_offset = 0, altitude; ! 4050: double h_rise, h_set, N; ! 4051: timelib_sll rise, set, transit; ! 4052: long time, retformat = 0; ! 4053: int rs; ! 4054: timelib_time *t; ! 4055: timelib_tzinfo *tzi; ! 4056: char *retstr; ! 4057: ! 4058: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ldddd", &time, &retformat, &latitude, &longitude, &zenith, &gmt_offset) == FAILURE) { ! 4059: RETURN_FALSE; ! 4060: } ! 4061: ! 4062: switch (ZEND_NUM_ARGS()) { ! 4063: case 1: ! 4064: retformat = SUNFUNCS_RET_STRING; ! 4065: case 2: ! 4066: latitude = INI_FLT("date.default_latitude"); ! 4067: case 3: ! 4068: longitude = INI_FLT("date.default_longitude"); ! 4069: case 4: ! 4070: if (calc_sunset) { ! 4071: zenith = INI_FLT("date.sunset_zenith"); ! 4072: } else { ! 4073: zenith = INI_FLT("date.sunrise_zenith"); ! 4074: } ! 4075: case 5: ! 4076: case 6: ! 4077: break; ! 4078: default: ! 4079: php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid format"); ! 4080: RETURN_FALSE; ! 4081: break; ! 4082: } ! 4083: if (retformat != SUNFUNCS_RET_TIMESTAMP && ! 4084: retformat != SUNFUNCS_RET_STRING && ! 4085: retformat != SUNFUNCS_RET_DOUBLE) ! 4086: { ! 4087: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong return format given, pick one of SUNFUNCS_RET_TIMESTAMP, SUNFUNCS_RET_STRING or SUNFUNCS_RET_DOUBLE"); ! 4088: RETURN_FALSE; ! 4089: } ! 4090: altitude = 90 - zenith; ! 4091: ! 4092: /* Initialize time struct */ ! 4093: t = timelib_time_ctor(); ! 4094: tzi = get_timezone_info(TSRMLS_C); ! 4095: t->tz_info = tzi; ! 4096: t->zone_type = TIMELIB_ZONETYPE_ID; ! 4097: ! 4098: if (ZEND_NUM_ARGS() <= 5) { ! 4099: gmt_offset = timelib_get_current_offset(t) / 3600; ! 4100: } ! 4101: ! 4102: timelib_unixtime2local(t, time); ! 4103: rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit); ! 4104: timelib_time_dtor(t); ! 4105: ! 4106: if (rs != 0) { ! 4107: RETURN_FALSE; ! 4108: } ! 4109: ! 4110: if (retformat == SUNFUNCS_RET_TIMESTAMP) { ! 4111: RETURN_LONG(calc_sunset ? set : rise); ! 4112: } ! 4113: N = (calc_sunset ? h_set : h_rise) + gmt_offset; ! 4114: ! 4115: if (N > 24 || N < 0) { ! 4116: N -= floor(N / 24) * 24; ! 4117: } ! 4118: ! 4119: switch (retformat) { ! 4120: case SUNFUNCS_RET_STRING: ! 4121: spprintf(&retstr, 0, "%02d:%02d", (int) N, (int) (60 * (N - (int) N))); ! 4122: RETURN_STRINGL(retstr, 5, 0); ! 4123: break; ! 4124: case SUNFUNCS_RET_DOUBLE: ! 4125: RETURN_DOUBLE(N); ! 4126: break; ! 4127: } ! 4128: } ! 4129: /* }}} */ ! 4130: ! 4131: /* {{{ proto mixed date_sunrise(mixed time [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]]) ! 4132: Returns time of sunrise for a given day and location */ ! 4133: PHP_FUNCTION(date_sunrise) ! 4134: { ! 4135: php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); ! 4136: } ! 4137: /* }}} */ ! 4138: ! 4139: /* {{{ proto mixed date_sunset(mixed time [, int format [, float latitude [, float longitude [, float zenith [, float gmt_offset]]]]]) ! 4140: Returns time of sunset for a given day and location */ ! 4141: PHP_FUNCTION(date_sunset) ! 4142: { ! 4143: php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ! 4144: } ! 4145: /* }}} */ ! 4146: ! 4147: /* {{{ proto array date_sun_info(long time, float latitude, float longitude) ! 4148: Returns an array with information about sun set/rise and twilight begin/end */ ! 4149: PHP_FUNCTION(date_sun_info) ! 4150: { ! 4151: long time; ! 4152: double latitude, longitude; ! 4153: timelib_time *t, *t2; ! 4154: timelib_tzinfo *tzi; ! 4155: int rs; ! 4156: timelib_sll rise, set, transit; ! 4157: int dummy; ! 4158: double ddummy; ! 4159: ! 4160: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldd", &time, &latitude, &longitude) == FAILURE) { ! 4161: RETURN_FALSE; ! 4162: } ! 4163: /* Initialize time struct */ ! 4164: t = timelib_time_ctor(); ! 4165: tzi = get_timezone_info(TSRMLS_C); ! 4166: t->tz_info = tzi; ! 4167: t->zone_type = TIMELIB_ZONETYPE_ID; ! 4168: timelib_unixtime2local(t, time); ! 4169: ! 4170: /* Setup */ ! 4171: t2 = timelib_time_ctor(); ! 4172: array_init(return_value); ! 4173: ! 4174: /* Get sun up/down and transit */ ! 4175: rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit); ! 4176: switch (rs) { ! 4177: case -1: /* always below */ ! 4178: add_assoc_bool(return_value, "sunrise", 0); ! 4179: add_assoc_bool(return_value, "sunset", 0); ! 4180: break; ! 4181: case 1: /* always above */ ! 4182: add_assoc_bool(return_value, "sunrise", 1); ! 4183: add_assoc_bool(return_value, "sunset", 1); ! 4184: break; ! 4185: default: ! 4186: t2->sse = rise; ! 4187: add_assoc_long(return_value, "sunrise", timelib_date_to_int(t2, &dummy)); ! 4188: t2->sse = set; ! 4189: add_assoc_long(return_value, "sunset", timelib_date_to_int(t2, &dummy)); ! 4190: } ! 4191: t2->sse = transit; ! 4192: add_assoc_long(return_value, "transit", timelib_date_to_int(t2, &dummy)); ! 4193: ! 4194: /* Get civil twilight */ ! 4195: rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -6.0, 0, &ddummy, &ddummy, &rise, &set, &transit); ! 4196: switch (rs) { ! 4197: case -1: /* always below */ ! 4198: add_assoc_bool(return_value, "civil_twilight_begin", 0); ! 4199: add_assoc_bool(return_value, "civil_twilight_end", 0); ! 4200: break; ! 4201: case 1: /* always above */ ! 4202: add_assoc_bool(return_value, "civil_twilight_begin", 1); ! 4203: add_assoc_bool(return_value, "civil_twilight_end", 1); ! 4204: break; ! 4205: default: ! 4206: t2->sse = rise; ! 4207: add_assoc_long(return_value, "civil_twilight_begin", timelib_date_to_int(t2, &dummy)); ! 4208: t2->sse = set; ! 4209: add_assoc_long(return_value, "civil_twilight_end", timelib_date_to_int(t2, &dummy)); ! 4210: } ! 4211: ! 4212: /* Get nautical twilight */ ! 4213: rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -12.0, 0, &ddummy, &ddummy, &rise, &set, &transit); ! 4214: switch (rs) { ! 4215: case -1: /* always below */ ! 4216: add_assoc_bool(return_value, "nautical_twilight_begin", 0); ! 4217: add_assoc_bool(return_value, "nautical_twilight_end", 0); ! 4218: break; ! 4219: case 1: /* always above */ ! 4220: add_assoc_bool(return_value, "nautical_twilight_begin", 1); ! 4221: add_assoc_bool(return_value, "nautical_twilight_end", 1); ! 4222: break; ! 4223: default: ! 4224: t2->sse = rise; ! 4225: add_assoc_long(return_value, "nautical_twilight_begin", timelib_date_to_int(t2, &dummy)); ! 4226: t2->sse = set; ! 4227: add_assoc_long(return_value, "nautical_twilight_end", timelib_date_to_int(t2, &dummy)); ! 4228: } ! 4229: ! 4230: /* Get astronomical twilight */ ! 4231: rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -18.0, 0, &ddummy, &ddummy, &rise, &set, &transit); ! 4232: switch (rs) { ! 4233: case -1: /* always below */ ! 4234: add_assoc_bool(return_value, "astronomical_twilight_begin", 0); ! 4235: add_assoc_bool(return_value, "astronomical_twilight_end", 0); ! 4236: break; ! 4237: case 1: /* always above */ ! 4238: add_assoc_bool(return_value, "astronomical_twilight_begin", 1); ! 4239: add_assoc_bool(return_value, "astronomical_twilight_end", 1); ! 4240: break; ! 4241: default: ! 4242: t2->sse = rise; ! 4243: add_assoc_long(return_value, "astronomical_twilight_begin", timelib_date_to_int(t2, &dummy)); ! 4244: t2->sse = set; ! 4245: add_assoc_long(return_value, "astronomical_twilight_end", timelib_date_to_int(t2, &dummy)); ! 4246: } ! 4247: timelib_time_dtor(t); ! 4248: timelib_time_dtor(t2); ! 4249: } ! 4250: /* }}} */ ! 4251: /* ! 4252: * Local variables: ! 4253: * tab-width: 4 ! 4254: * c-basic-offset: 4 ! 4255: * End: ! 4256: * vim600: fdm=marker ! 4257: * vim: noet sw=4 ts=4 ! 4258: */