Skip to content

Commit 29a3729

Browse files
committed
PHPC-536: UTCDateTime construction from DateTimeInterface or current time
1 parent a8473b0 commit 29a3729

File tree

5 files changed

+168
-12
lines changed

5 files changed

+168
-12
lines changed

src/BSON/UTCDateTime.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,16 @@
3333
#include <php_ini.h>
3434
#include <ext/standard/info.h>
3535
#include <Zend/zend_interfaces.h>
36+
#include <ext/date/php_date.h>
3637
#include <ext/spl/spl_iterators.h>
3738
#include <ext/date/php_date.h>
3839
/* Our Compatability header */
3940
#include "phongo_compat.h"
4041

42+
#ifdef PHP_WIN32
43+
#include "win32/time.h"
44+
#endif
45+
4146
/* Our stuffz */
4247
#include "php_phongo.h"
4348
#include "php_bson.h"
@@ -47,17 +52,60 @@ PHONGO_API zend_class_entry *php_phongo_utcdatetime_ce;
4752

4853
zend_object_handlers php_phongo_handler_utcdatetime;
4954

50-
/* {{{ proto BSON\UTCDateTime UTCDateTime::__construct(integer $milliseconds)
55+
static void php_phongo_utcdatetime_init_from_current_time(php_phongo_utcdatetime_t *intern)
56+
{
57+
int64_t sec, usec;
58+
struct timeval cur_time;
59+
60+
gettimeofday(&cur_time, NULL);
61+
sec = cur_time.tv_sec;
62+
usec = cur_time.tv_usec;
63+
64+
intern->milliseconds = (sec * 1000) + (usec / 1000);
65+
}
66+
67+
static void php_phongo_utcdatetime_init_from_date(php_phongo_utcdatetime_t *intern, php_date_obj *datetime_obj)
68+
{
69+
int64_t sec, usec;
70+
71+
/* The following assignments use the same logic as date_format() in php_date.c */
72+
sec = datetime_obj->time->sse;
73+
usec = (int64_t) floor(datetime_obj->time->f * 1000000 + 0.5);
74+
75+
intern->milliseconds = (sec * 1000) + (usec / 1000);
76+
}
77+
78+
/* {{{ proto BSON\UTCDateTime UTCDateTime::__construct([integer|DateTimeInterface $milliseconds = null])
5179
Construct a new UTCDateTime */
5280
PHP_METHOD(UTCDateTime, __construct)
5381
{
5482
php_phongo_utcdatetime_t *intern;
55-
zend_error_handling error_handling;
56-
83+
zend_error_handling error_handling;
84+
zval *datetime = NULL;
5785

5886
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
5987
intern = Z_UTCDATETIME_OBJ_P(getThis());
6088

89+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|o!", &datetime) == SUCCESS) {
90+
if (datetime == NULL) {
91+
php_phongo_utcdatetime_init_from_current_time(intern);
92+
} else if (instanceof_function(Z_OBJCE_P(datetime), php_date_get_date_ce() TSRMLS_CC)) {
93+
php_phongo_utcdatetime_init_from_date(intern, Z_PHPDATE_P(datetime));
94+
#if PHP_VERSION_ID >= 50500
95+
} else if (instanceof_function(Z_OBJCE_P(datetime), php_date_get_immutable_ce() TSRMLS_CC)) {
96+
php_phongo_utcdatetime_init_from_date(intern, Z_PHPDATE_P(datetime));
97+
#endif
98+
} else {
99+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC,
100+
"Expected instance of DateTimeInterface, %s given",
101+
phongo_str(Z_OBJCE_P(datetime)->name)
102+
);
103+
}
104+
105+
zend_restore_error_handling(&error_handling TSRMLS_CC);
106+
return;
107+
}
108+
61109
#if SIZEOF_PHONGO_LONG == 8
62110
{
63111
phongo_long milliseconds;

tests/bson/bson-utcdatetime-004.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
BSON BSON\UTCDateTime constructor defaults to current time
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$tests = [
10+
new MongoDB\BSON\UTCDateTime,
11+
new MongoDB\BSON\UTCDateTime(null),
12+
];
13+
14+
foreach ($tests as $test) {
15+
var_dump($test);
16+
}
17+
18+
?>
19+
===DONE===
20+
<?php exit(0); ?>
21+
--EXPECTF--
22+
object(%SBSON\UTCDateTime)#%d (%d) {
23+
["milliseconds"]=>
24+
int(%d)
25+
}
26+
object(%SBSON\UTCDateTime)#%d (%d) {
27+
["milliseconds"]=>
28+
int(%d)
29+
}
30+
===DONE===

tests/bson/bson-utcdatetime-005.phpt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
BSON BSON\UTCDateTime construction from DateTime
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$tests = [
10+
new DateTime(),
11+
new DateTime('@1215282385'),
12+
new DateTime('2011-01-01T15:03:01.012345Z'),
13+
new DateTime('2050-11-12T13:14:15.999999Z'),
14+
];
15+
16+
foreach ($tests as $test) {
17+
var_dump(new MongoDB\BSON\UTCDateTime($test));
18+
}
19+
20+
?>
21+
===DONE===
22+
<?php exit(0); ?>
23+
--EXPECTF--
24+
object(%SBSON\UTCDateTime)#%d (%d) {
25+
["milliseconds"]=>
26+
int(%d000)
27+
}
28+
object(%SBSON\UTCDateTime)#%d (%d) {
29+
["milliseconds"]=>
30+
int(1215282385000)
31+
}
32+
object(%SBSON\UTCDateTime)#%d (%d) {
33+
["milliseconds"]=>
34+
int(1293894181012)
35+
}
36+
object(%SBSON\UTCDateTime)#%d (%d) {
37+
["milliseconds"]=>
38+
int(2551871655999)
39+
}
40+
===DONE===

tests/bson/bson-utcdatetime-006.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
BSON BSON\UTCDateTime construction from DateTimeImmutable
3+
--SKIPIF--
4+
<?php if (!version_compare(phpversion(), "5.5", '>=')) echo "skip >= PHP 5.5 needed\n"; ?>
5+
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
$tests = [
11+
new DateTimeImmutable(),
12+
new DateTimeImmutable('@1215282385'),
13+
new DateTimeImmutable('2011-01-01T15:03:01.012345Z'),
14+
new DateTimeImmutable('2050-11-12T13:14:15.999999Z'),
15+
];
16+
17+
foreach ($tests as $test) {
18+
var_dump(new MongoDB\BSON\UTCDateTime($test));
19+
}
20+
21+
?>
22+
===DONE===
23+
<?php exit(0); ?>
24+
--EXPECTF--
25+
object(%SBSON\UTCDateTime)#%d (%d) {
26+
["milliseconds"]=>
27+
int(%d000)
28+
}
29+
object(%SBSON\UTCDateTime)#%d (%d) {
30+
["milliseconds"]=>
31+
int(1215282385000)
32+
}
33+
object(%SBSON\UTCDateTime)#%d (%d) {
34+
["milliseconds"]=>
35+
int(1293894181012)
36+
}
37+
object(%SBSON\UTCDateTime)#%d (%d) {
38+
["milliseconds"]=>
39+
int(2551871655999)
40+
}
41+
===DONE===
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
--TEST--
2-
BSON BSON\UTCDateTime #001 error
3-
--INI--
4-
date.timezone=America/Los_Angeles
2+
BSON BSON\UTCDateTime requires object argument to implement DateTimeInterface
53
--SKIPIF--
6-
<?php if (defined("HHVM_VERSION_ID")) exit("skip HHVM handles parameter parsing differently"); ?>
74
<?php require __DIR__ . "/../utils/basic-skipif.inc"?>
85
--FILE--
96
<?php
107
require_once __DIR__ . "/../utils/basic.inc";
118

12-
throws(function() {
13-
$classname = BSON_NAMESPACE . "\\UTCDateTime";
14-
new $classname;
15-
}, "MongoDB\\Driver\\Exception\\InvalidArgumentException");
9+
echo throws(function() {
10+
new MongoDB\BSON\UTCDateTime(new stdClass);
11+
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1612

1713
?>
1814
===DONE===
1915
<?php exit(0); ?>
20-
--EXPECTF--
16+
--EXPECT--
2117
OK: Got MongoDB\Driver\Exception\InvalidArgumentException
18+
Expected instance of DateTimeInterface, stdClass given
2219
===DONE===

0 commit comments

Comments
 (0)