Skip to content

Commit 3a2122b

Browse files
committed
Merge branch 'master' of github.com:hnw/php-timecop
2 parents c98f567 + 32e72dc commit 3a2122b

File tree

6 files changed

+171
-8
lines changed

6 files changed

+171
-8
lines changed

php_timecop.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ PHP_FUNCTION(timecop_strftime);
6363
PHP_FUNCTION(timecop_gmstrftime);
6464
PHP_FUNCTION(timecop_unixtojd);
6565
PHP_FUNCTION(timecop_date_create);
66+
PHP_FUNCTION(timecop_date_create_from_format);
6667

6768
PHP_METHOD(TimecopDateTime, __construct);
6869

tests/012.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Check for compareing TimecopDateTime instance
3+
--SKIPIF--
4+
<?php
5+
extension_loaded('timecop') or die('skip timecop not available');
6+
$required_class = array("timecopdatetime");
7+
foreach ($required_class as $class_name) {
8+
if (!class_exists($class_name)) {
9+
die("skip $class_name class is not available.");
10+
}
11+
}
12+
--INI--
13+
date.timezone=America/Los_Angeles
14+
timecop.func_override=0
15+
--FILE--
16+
<?php
17+
$dt1 = new TimecopDateTime("2012-01-02 12:00:00 JST");
18+
$dt2 = new TimecopDateTime("2012-01-02 12:00:00", new DateTimezone("Asia/Tokyo"));
19+
var_dump($dt1 == $dt2);
20+
$dt3 = new TimecopDateTime("2012-01-01 23:00:00 EST");
21+
var_dump($dt1 < $dt3);
22+
--EXPECT--
23+
bool(true)
24+
bool(true)

tests/013.phpt

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Check for clone TimecopDateTime instance
3+
--SKIPIF--
4+
<?php
5+
extension_loaded('timecop') or die('skip timecop not available');
6+
$required_class = array("timecopdatetime");
7+
foreach ($required_class as $class_name) {
8+
if (!class_exists($class_name)) {
9+
die("skip $class_name class is not available.");
10+
}
11+
}
12+
--INI--
13+
date.timezone=America/Los_Angeles
14+
timecop.func_override=0
15+
--FILE--
16+
<?php
17+
$dt1 = new TimecopDateTime("2012-01-01 12:00:00 GMT");
18+
$dt2 = clone $dt1;
19+
var_dump($dt2->format("c"));
20+
--EXPECT--
21+
string(25) "2012-01-01T12:00:00+00:00"

tests/overload_13.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,4 @@ string(25) "2012-03-31T12:34:56-07:00"
6464
string(25) "2012-03-03T01:23:45-08:00"
6565
string(25) "1970-01-01T19:00:00-05:00"
6666
string(25) "1970-01-02T00:00:00+00:00"
67-
string(25) "2012-02-29T18:23:45+09:00"
67+
string(25) "2012-02-29T18:23:45+09:00"

tests/overload_15.phpt

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--TEST--
2+
Function overrideing test for date_create_from_format
3+
--SKIPIF--
4+
<?php
5+
extension_loaded('timecop') or die('skip timecop not available');
6+
$required_func = array("date_create_from_format");
7+
foreach ($required_func as $func_name) {
8+
if (!function_exists($func_name)) {
9+
die("skip $func_name() function is not available.");
10+
}
11+
}
12+
$required_class = array("datetime");
13+
foreach ($required_class as $class_name) {
14+
if (!class_exists($class_name)) {
15+
die("skip $class_name class is not available.");
16+
}
17+
}
18+
if (version_compare(PHP_VERSION, "5.3.4", "<")) die("skip PHP 5.3.4+ required for this test");
19+
--INI--
20+
date.timezone=America/Los_Angeles
21+
--FILE--
22+
<?php
23+
24+
// checking class name of instance
25+
$dt0 = new DateTime();
26+
var_dump(get_class($dt0));
27+
$dt1 = DateTime::createFromFormat('U', 0);
28+
var_dump(get_class($dt1));
29+
30+
$dts = array(
31+
// constuctor with 2 argument(absolute format)
32+
date_create_from_format("Y-m-d H:i:s", "2012-03-31 12:34:56"),
33+
34+
// constuctor with 2 argument(including timezone info)
35+
date_create_from_format("Y-m-d H:i:s T", "1970-01-01 19:00:00 EST"),
36+
37+
// constuctor with 2 argument(unix time)
38+
date_create_from_format("U", "86400"),
39+
40+
// constuctor with 3 argument
41+
date_create_from_format("Y-m-d H:i:s", "2012-04-01 00:00:00", new DateTimezone("Asia/Tokyo")),
42+
43+
);
44+
45+
foreach ($dts as $dt) {
46+
var_dump($dt->format("c"));
47+
var_dump($dt->getTimezone()->getName());
48+
}
49+
50+
--EXPECT--
51+
string(15) "TimecopDateTime"
52+
string(15) "TimecopDateTime"
53+
string(25) "2012-03-31T12:34:56-07:00"
54+
string(19) "America/Los_Angeles"
55+
string(25) "1970-01-01T19:00:00-05:00"
56+
string(3) "EST"
57+
string(25) "1970-01-02T00:00:00+00:00"
58+
string(6) "+00:00"
59+
string(25) "2012-04-01T00:00:00+09:00"
60+
string(10) "Asia/Tokyo"

timecop.c

+64-7
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
#include "php.h"
2626
#include "php_ini.h"
2727
#include "ext/standard/info.h"
28+
#include "ext/date/php_date.h"
2829

2930
#if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
30-
#include "ext/date/php_date.h"
3131
#include "ext/date/lib/timelib.h"
3232
#endif
3333

@@ -66,6 +66,9 @@ static const struct timecop_override_def timecop_ovld_func[] = {
6666
{"gmstrftime", "timecop_gmstrftime", "timecop_orig_gmstrftime"},
6767
{"unixtojd", "timecop_unixtojd", "timecop_orig_unixtojd"},
6868
{"date_create", "timecop_date_create", "timecop_orig_date_create"},
69+
#if PHP_VERSION_ID >= 50300
70+
{"date_create_from_format", "timecop_date_create_from_format", "timecop_orig_date_create_from_format"},
71+
#endif
6972
{NULL, NULL, NULL}
7073
};
7174
/* }}} */
@@ -157,6 +160,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date_create, 0, 0, 0)
157160
ZEND_ARG_INFO(0, object)
158161
ZEND_END_ARG_INFO()
159162

163+
#if PHP_VERSION_ID >= 50300
164+
ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date_create_from_format, 0, 0, 2)
165+
ZEND_ARG_INFO(0, format)
166+
ZEND_ARG_INFO(0, time)
167+
ZEND_ARG_INFO(0, object)
168+
ZEND_END_ARG_INFO()
169+
#endif
170+
160171
#if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
161172
ZEND_BEGIN_ARG_INFO_EX(arginfo_timecop_date_method_timestamp_set, 0, 0, 1)
162173
ZEND_ARG_INFO(0, unixtimestamp)
@@ -184,6 +195,9 @@ const zend_function_entry timecop_functions[] = {
184195
PHP_FE(timecop_gmstrftime, arginfo_timecop_gmstrftime)
185196
PHP_FE(timecop_unixtojd, arginfo_timecop_unixtojd)
186197
PHP_FE(timecop_date_create, arginfo_timecop_date_create)
198+
#if PHP_VERSION_ID >= 50300
199+
PHP_FE(timecop_date_create_from_format, arginfo_timecop_date_create_from_format)
200+
#endif
187201
{NULL, NULL, NULL}
188202
};
189203
/* }}} */
@@ -194,6 +208,10 @@ const zend_function_entry timecop_functions[] = {
194208
static zend_function_entry timecop_datetime_class_functions[] = {
195209
PHP_ME(TimecopDateTime, __construct, arginfo_timecop_date_create,
196210
ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
211+
#if PHP_VERSION_ID >= 50300
212+
PHP_ME_MAPPING(createFromFormat, timecop_date_create_from_format, arginfo_timecop_date_create_from_format,
213+
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
214+
#endif
197215
#if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
198216
PHP_ME(TimecopDateTime, getTimestamp,
199217
arginfo_timecop_date_method_timestamp_get, 0)
@@ -251,7 +269,7 @@ static int restore_request_time(TSRMLS_D);
251269
static long timecop_current_timestamp(TSRMLS_D);
252270

253271
static int fill_mktime_params(zval ***params, const char *date_function_name, int from TSRMLS_DC);
254-
static int fix_datetime_timestamp(zval **datetime_obj, zval *time TSRMLS_DC);
272+
static int fix_datetime_timestamp(zval **datetime_obj, zval *time, zval *timezone_obj TSRMLS_DC);
255273

256274
static void _timecop_call_function(INTERNAL_FUNCTION_PARAMETERS, const char *function_name, zval **retval_ptr_ptr, int index_to_fill_timestamp);
257275
static void _timecop_call_mktime(INTERNAL_FUNCTION_PARAMETERS, const char *mktime_function_name, const char *date_function_name, zval **retval_ptr_ptr);
@@ -520,7 +538,6 @@ static int update_request_time(long unixtime TSRMLS_DC)
520538
MAKE_STD_ZVAL(tmp);
521539
ZVAL_LONG(tmp, unixtime);
522540
add_assoc_zval(*server_vars, "REQUEST_TIME", tmp);
523-
zval_dtor(tmp);
524541
}
525542

526543
return SUCCESS;
@@ -538,7 +555,6 @@ static int restore_request_time(TSRMLS_D)
538555
Z_TYPE_PP(server_vars) == IS_ARRAY &&
539556
zend_hash_find(Z_ARRVAL_PP(server_vars), "REQUEST_TIME", sizeof("REQUEST_TIME"), (void **) &request_time) == SUCCESS) {
540557
add_assoc_zval(*server_vars, "REQUEST_TIME", orig_request_time);
541-
zval_dtor(orig_request_time);
542558
TIMECOP_G(orig_request_time) = NULL;
543559
}
544560
return SUCCESS;
@@ -589,10 +605,11 @@ static int fill_mktime_params(zval ***params, const char *date_function_name, in
589605
return MKTIME_NUM_ARGS;
590606
}
591607

592-
static int fix_datetime_timestamp(zval **datetime_obj, zval *time TSRMLS_DC)
608+
static int fix_datetime_timestamp(zval **datetime_obj, zval *time, zval *timezone_obj TSRMLS_DC)
593609
{
594610
zval *orig_timestamp, *fixed_timestamp;
595611
zval now;
612+
zval *orig_zonename;
596613

597614
INIT_ZVAL(now);
598615
ZVAL_STRING(&now, "now", 0);
@@ -611,7 +628,18 @@ static int fix_datetime_timestamp(zval **datetime_obj, zval *time TSRMLS_DC)
611628
}
612629

613630
zend_call_method_with_0_params(datetime_obj, Z_OBJCE_PP(datetime_obj), NULL, "gettimestamp", &orig_timestamp);
631+
if (timezone_obj) {
632+
zval *zonename;
633+
zend_call_method_with_0_params(&timezone_obj, Z_OBJCE_PP(&timezone_obj), NULL, "getname", &zonename);
634+
zend_call_method_with_0_params(NULL, NULL, NULL, "date_default_timezone_get", &orig_zonename);
635+
zend_call_method_with_1_params(NULL, NULL, NULL, "date_default_timezone_set", NULL, zonename);
636+
zval_ptr_dtor(&zonename);
637+
}
614638
zend_call_method_with_1_params(NULL, NULL, NULL, "timecop_strtotime", &fixed_timestamp, time);
639+
if (timezone_obj) {
640+
zend_call_method_with_1_params(NULL, NULL, NULL, "date_default_timezone_set", NULL, orig_zonename);
641+
zval_ptr_dtor(&orig_zonename);
642+
}
615643

616644
if (Z_TYPE_P(fixed_timestamp) == IS_BOOL && Z_BVAL_P(fixed_timestamp) == 0) {
617645
// timecop_strtotime($time) === false
@@ -881,14 +909,39 @@ PHP_FUNCTION(timecop_date_create)
881909
}
882910
/* }}} */
883911

912+
#if PHP_VERSION_ID >= 50300
913+
/* {{{ proto TimecopDateTime timecop_date_create_from_format(string format, string time[, DateTimeZone object])
914+
Returns new TimecopDateTime object
915+
*/
916+
PHP_FUNCTION(timecop_date_create_from_format)
917+
{
918+
zval *timezone_object = NULL;
919+
char *time_str = NULL, *format_str = NULL;
920+
int time_str_len = 0, format_str_len = 0;
921+
922+
#if PHP_VERSION_ID <= 50303
923+
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Currently this method is unsupported on PHP 5.3.0-5.3.3. Please upgrade PHP to 5.3.4+.");
924+
#else
925+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|O", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, php_date_get_timezone_ce()) == FAILURE) {
926+
RETURN_FALSE;
927+
}
928+
929+
php_timecop_date_instantiate(TIMECOP_G(ce_TimecopDateTime), return_value TSRMLS_CC);
930+
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)) {
931+
RETURN_FALSE;
932+
}
933+
#endif
934+
}
935+
/* }}} */
936+
#endif
937+
884938
/* {{{ proto TimecopDateTime::__construct([string time[, DateTimeZone object]])
885939
Creates new TimecopDateTime object
886940
*/
887941
PHP_METHOD(TimecopDateTime, __construct)
888942
{
889943
zval ***params;
890944
zval *obj = getThis();
891-
zval *time = NULL;
892945
zend_class_entry *datetime_ce;
893946

894947
params = (zval ***) safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval **), 0);
@@ -902,10 +955,14 @@ PHP_METHOD(TimecopDateTime, __construct)
902955
call_constructor(&obj, TIMECOP_G(ce_DateTime), params, ZEND_NUM_ARGS() TSRMLS_CC);
903956

904957
if (!EG(exception)) {
958+
zval *time = NULL, *timezone_obj = NULL;
905959
if (ZEND_NUM_ARGS() >= 1) {
906960
time = *params[0];
907961
}
908-
fix_datetime_timestamp(&obj, time TSRMLS_CC);
962+
if (ZEND_NUM_ARGS() >= 2) {
963+
timezone_obj = *params[1];
964+
}
965+
fix_datetime_timestamp(&obj, time, timezone_obj TSRMLS_CC);
909966
}
910967

911968
efree(params);

0 commit comments

Comments
 (0)