PageRenderTime 70ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/date/php_date.c

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