php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
dateformat_parse.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | This source file is subject to version 3.01 of the PHP license, |
4 | that is bundled with this package in the file LICENSE, and is |
5 | available through the world-wide-web at the following url: |
6 | https://www.php.net/license/3_01.txt |
7 | If you did not receive a copy of the PHP license and are unable to |
8 | obtain it through the world-wide-web, please send a note to |
9 | license@php.net so we can mail you a copy immediately. |
10 +----------------------------------------------------------------------+
11 | Authors: Kirti Velankar <kirtig@yahoo-inc.com> |
12 +----------------------------------------------------------------------+
13*/
14
15#ifdef HAVE_CONFIG_H
16#include <config.h>
17#endif
18
19#include <unicode/ustring.h>
20#include <math.h>
21
22#include "php_intl.h"
23#include "intl_convert.h"
24#include "dateformat.h"
25#include "dateformat_class.h"
26#include "dateformat_data.h"
27
28/* {{{
29 * Internal function which calls the udat_parse
30 * param int store_error acts like a boolean
31 * if set to 1 - store any error encountered in the parameter parse_error
32 * if set to 0 - no need to store any error encountered in the parameter parse_error
33*/
34static void internal_parse_to_timestamp(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, bool update_calendar, zval *return_value)
35{
36 double result = 0;
37 UDate timestamp =0;
38 UChar* text_utf16 = NULL;
39 int32_t text_utf16_len = 0;
40
41 /* Convert timezone to UTF-16. */
42 intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo));
43 INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" );
44
45 if (UNEXPECTED(update_calendar)) {
46 UCalendar *parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo));
47 udat_parseCalendar(DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
48 if (text_utf16) {
49 efree(text_utf16);
50 }
51 INTL_METHOD_CHECK_STATUS( dfo, "Calendar parsing failed" );
52 timestamp = ucal_getMillis( parsed_calendar, &INTL_DATA_ERROR_CODE(dfo));
53 } else {
54 timestamp = udat_parse(DATE_FORMAT_OBJECT(dfo), text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
55 if (text_utf16) {
56 efree(text_utf16);
57 }
58 }
59
60 INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" );
61 /* Since return is in sec. */
62 result = (double)timestamp / U_MILLIS_PER_SECOND;
63 if (result > (double)LONG_MAX || result < (double)LONG_MIN) {
65 } else {
67 }
68}
69/* }}} */
70
71static void add_to_localtime_arr( IntlDateFormatter_object *dfo, zval* return_value, const UCalendar *parsed_calendar, zend_long calendar_field, char* key_name)
72{
73 zend_long calendar_field_val = ucal_get( parsed_calendar, calendar_field, &INTL_DATA_ERROR_CODE(dfo));
74 INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : could not get a field from calendar" );
75
76 if( strcmp(key_name, CALENDAR_YEAR )==0 ){
77 /* since tm_year is years from 1900 */
78 add_assoc_long( return_value, key_name,( calendar_field_val-1900) );
79 }else if( strcmp(key_name, CALENDAR_WDAY )==0 ){
80 /* since tm_wday starts from 0 whereas ICU WDAY start from 1 */
81 add_assoc_long( return_value, key_name,( calendar_field_val-1) );
82 }else{
83 add_assoc_long( return_value, key_name, calendar_field_val );
84 }
85}
86
87/* {{{ Internal function which calls the udat_parseCalendar */
88static void internal_parse_to_localtime(IntlDateFormatter_object *dfo, char* text_to_parse, size_t text_len, int32_t *parse_pos, zval *return_value)
89{
90 UCalendar *parsed_calendar = NULL;
91 UChar* text_utf16 = NULL;
92 int32_t text_utf16_len = 0;
93 zend_long isInDST = 0;
94
95 /* Convert timezone to UTF-16. */
96 intl_convert_utf8_to_utf16(&text_utf16, &text_utf16_len, text_to_parse, text_len, &INTL_DATA_ERROR_CODE(dfo));
97 INTL_METHOD_CHECK_STATUS(dfo, "Error converting timezone to UTF-16" );
98
99 parsed_calendar = (UCalendar *)udat_getCalendar(DATE_FORMAT_OBJECT(dfo));
100 udat_parseCalendar( DATE_FORMAT_OBJECT(dfo), parsed_calendar, text_utf16, text_utf16_len, parse_pos, &INTL_DATA_ERROR_CODE(dfo));
101
102 if (text_utf16) {
103 efree(text_utf16);
104 }
105
106 INTL_METHOD_CHECK_STATUS( dfo, "Date parsing failed" );
107
108
110 /* Add entries from various fields of the obtained parsed_calendar */
111 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_SECOND, CALENDAR_SEC);
112 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MINUTE, CALENDAR_MIN);
113 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_HOUR_OF_DAY, CALENDAR_HOUR);
114 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_YEAR, CALENDAR_YEAR);
115 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_MONTH, CALENDAR_MDAY);
116 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_WEEK, CALENDAR_WDAY);
117 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_DAY_OF_YEAR, CALENDAR_YDAY);
118 add_to_localtime_arr( dfo, return_value, parsed_calendar, UCAL_MONTH, CALENDAR_MON);
119
120 /* Is in DST? */
121 isInDST = ucal_inDaylightTime(parsed_calendar , &INTL_DATA_ERROR_CODE(dfo));
122 INTL_METHOD_CHECK_STATUS( dfo, "Date parsing - localtime failed : while checking if currently in DST." );
123 add_assoc_long( return_value, CALENDAR_ISDST,isInDST==1);
124}
125/* }}} */
126
127
128/* {{{ Parse the string $value starting at parse_pos to a Unix timestamp -int */
130{
131 char* text_to_parse = NULL;
132 size_t text_len =0;
133 zval* z_parse_pos = NULL;
134 int32_t parse_pos = -1;
135
137
138 /* Parse parameters. */
140 &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){
142 }
143
144 /* Fetch the object. */
146
147 if (z_parse_pos) {
148 zval *z_parse_pos_tmp = z_parse_pos;
149 ZVAL_DEREF(z_parse_pos_tmp);
150 zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp);
151 if (ZEND_LONG_INT_OVFL(long_parse_pos)) {
153 intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0);
155 }
156 parse_pos = (int32_t)long_parse_pos;
157 if ((size_t)parse_pos > text_len) {
159 }
160 }
161 internal_parse_to_timestamp( dfo, text_to_parse, text_len, z_parse_pos ? &parse_pos : NULL, false, return_value);
162 if (z_parse_pos) {
163 ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos);
164 }
165}
166/* }}} */
167
169{
170 zend_string *text_to_parse = NULL;
171 zval* z_parse_pos = NULL;
172 int32_t parse_pos = -1;
173
175
177 Z_PARAM_STR(text_to_parse)
179 Z_PARAM_ZVAL(z_parse_pos)
181
182 object = ZEND_THIS;
183
184 /* Fetch the object. */
186
187 if (z_parse_pos) {
188 zval *z_parse_pos_tmp = z_parse_pos;
189 ZVAL_DEREF(z_parse_pos_tmp);
190 bool failed = false;
191 zend_long long_parse_pos = zval_try_get_long(z_parse_pos_tmp, &failed);
192 if (failed) {
193 zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos_tmp));
195 }
196 if (ZEND_LONG_INT_OVFL(long_parse_pos)) {
198 intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0);
200 }
201 parse_pos = (int32_t)long_parse_pos;
202 if (parse_pos != -1 && (size_t)parse_pos > ZSTR_LEN(text_to_parse)) {
204 }
205 }
206 internal_parse_to_timestamp( dfo, ZSTR_VAL(text_to_parse), ZSTR_LEN(text_to_parse), z_parse_pos ? &parse_pos : NULL, true, return_value);
207 if (z_parse_pos) {
208 ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos);
209 }
210}
211
212/* {{{ Parse the string $value to a localtime array */
214{
215 char* text_to_parse = NULL;
216 size_t text_len =0;
217 zval* z_parse_pos = NULL;
218 int32_t parse_pos = -1;
219
221
222 /* Parse parameters. */
224 &object, IntlDateFormatter_ce_ptr, &text_to_parse, &text_len, &z_parse_pos ) == FAILURE ){
226 }
227
228 /* Fetch the object. */
230
231 if (z_parse_pos) {
232 zval *z_parse_pos_tmp = z_parse_pos;
233 ZVAL_DEREF(z_parse_pos_tmp);
234 zend_long long_parse_pos = zval_get_long(z_parse_pos_tmp);
235 if (ZEND_LONG_INT_OVFL(long_parse_pos)) {
237 intl_error_set_custom_msg(NULL, "String index is out of valid range.", 0);
239 }
240 parse_pos = (int32_t)long_parse_pos;
241 if((size_t)parse_pos > text_len) {
243 }
244 }
245 internal_parse_to_localtime( dfo, text_to_parse, text_len, z_parse_pos?&parse_pos:NULL, return_value);
246 if (z_parse_pos) {
247 ZEND_TRY_ASSIGN_REF_LONG(z_parse_pos, parse_pos);
248 }
249}
250/* }}} */
floor(int|float $num)
ceil(int|float $num)
const U_ILLEGAL_ARGUMENT_ERROR
#define CALENDAR_YEAR
Definition dateformat.h:32
#define CALENDAR_MIN
Definition dateformat.h:28
#define CALENDAR_ISDST
Definition dateformat.h:35
#define CALENDAR_WDAY
Definition dateformat.h:33
#define CALENDAR_YDAY
Definition dateformat.h:34
#define CALENDAR_SEC
Definition dateformat.h:27
#define CALENDAR_HOUR
Definition dateformat.h:29
#define CALENDAR_MDAY
Definition dateformat.h:30
#define CALENDAR_MON
Definition dateformat.h:31
zend_class_entry * IntlDateFormatter_ce_ptr
#define DATE_FORMAT_METHOD_FETCH_OBJECT
#define DATE_FORMAT_OBJECT(dfo)
#define DATE_FORMAT_METHOD_INIT_VARS
#define NULL
Definition gdcache.h:45
void intl_convert_utf8_to_utf16(UChar **target, int32_t *target_len, const char *src, size_t src_len, UErrorCode *status)
#define INTL_DATA_ERROR_CODE(obj)
Definition intl_data.h:40
#define INTL_METHOD_CHECK_STATUS(obj, msg)
Definition intl_data.h:66
void intl_error_set_code(intl_error *err, UErrorCode err_code)
Definition intl_error.c:141
void intl_error_set_custom_msg(intl_error *err, const char *msg, int copyMsg)
Definition intl_error.c:90
#define PHP_FUNCTION
Definition php.h:364
#define PHP_METHOD
Definition php.h:365
datefmt_localtime(IntlDateFormatter $formatter, string $string, &$offset=null)
datefmt_parse(IntlDateFormatter $formatter, string $string, &$offset=null)
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec,...)
Definition zend_API.c:1314
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define ZEND_TRY_ASSIGN_REF_LONG(zv, lval)
Definition zend_API.h:1205
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_THIS
Definition zend_API.h:523
#define Z_PARAM_ZVAL(dest)
Definition zend_API.h:2100
#define getThis()
Definition zend_API.h:526
#define array_init(arg)
Definition zend_API.h:537
#define efree(ptr)
Definition zend_alloc.h:155
struct _zval_struct zval
strcmp(string $string1, string $string2)
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
ZEND_API zend_long ZEND_FASTCALL zval_try_get_long(const zval *op, bool *failed)
#define LONG_MAX
#define UNEXPECTED(condition)
#define LONG_MIN
#define ZEND_LONG_INT_OVFL(zlong)
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
@ FAILURE
Definition zend_types.h:61
#define ZVAL_DOUBLE(z, d)
zval * return_value
bool result