[ACCEPTED]-PHP DateTime microseconds always returns 0-datetime
This seems to work, although it seems illogical 2 that http://us.php.net/date documents the microsecond specifier 1 yet doesn't really support it:
function getTimestamp()
{
return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8);
}
You can specify that your input contains 6 microseconds when constructing a DateTime
object, and 5 use microtime(true)
directly as the input.
Unfortunately, this 4 will fail if you hit an exact second, because 3 there will be no .
in the microtime output; so 2 use sprintf
to force it to contain a .0
in that case:
date_create_from_format(
'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');
Or 1 equivalently (more OO-style)
DateTime::createFromFormat(
'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');
This function pulled from http://us3.php.net/date
function udate($format, $utimestamp = null)
{
if (is_null($utimestamp))
$utimestamp = microtime(true);
$timestamp = floor($utimestamp);
$milliseconds = round(($utimestamp - $timestamp) * 1000000);
return date(preg_replace('`(?<!\\\\)u`', $milliseconds, $format), $timestamp);
}
echo udate('H:i:s.u'); // 19:40:56.78128
Very screwy you 2 have to implement this function to get "u" to 1 work... :\
Try this and it shows micro seconds:
$t = microtime(true);
$micro = sprintf("%06d",($t - floor($t)) * 1000000);
$d = new DateTime( date('Y-m-d H:i:s.'.$micro,$t) );
print $d->format("Y-m-d H:i:s.u");
0
\DateTime::createFromFormat('U.u', microtime(true));
Will give you (at least on most systems):
object(DateTime)(
'date' => '2015-03-09 17:27:39.456200',
'timezone_type' => 3,
'timezone' => 'Australia/Darwin'
)
But 6 there is a loss of precision because of 5 PHP float rounding. It's not truly microseconds.
Update
This 4 is probably the best compromise of the createFromFormat()
options, and 3 provides full precision.
\DateTime::createFromFormat('0.u00 U', microtime());
gettimeofday()
More explicit, and 2 maybe more robust. Solves the bug found 1 by Xavi.
$time = gettimeofday();
\DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
Right, I'd like to clear this up once and 14 for all.
An explanation of how to display 13 the ISO 8601 format date & time in PHP with 12 milliseconds and microseconds...
milliseconds or 'ms' have 4 digits after the decimal point e.g. 0.1234. microseconds or 'µs' have 7 digits after decimal. Seconds fractions/names explanation here
PHP's date()
function does 11 not behave entirely as expected with milliseconds 10 or microseconds as it will only except an 9 integer, as explained in the php date docs under format 8 character 'u'.
Based on Lucky's comment idea 7 (here), but with corrected PHP syntax and properly 6 handling seconds formatting (Lucky's code added an incorrect extra '0' after the seconds)
These also eliminate 5 race conditions and correctly formats the 4 seconds.
PHP Date with milliseconds
Working Equivalent of date('Y-m-d H:i:s').".$milliseconds";
list($sec, $usec) = explode('.', microtime(true));
echo date('Y-m-d H:i:s.', $sec) . $usec;
Output = 2016-07-12 16:27:08.5675
PHP Date with microseconds
Working 3 Equivalent of date('Y-m-d H:i:s').".$microseconds";
or date('Y-m-d H:i:s.u')
if the date function 2 behaved as expected with microseconds/microtime()
/'u'
list($usec, $sec) = explode(' ', microtime());
echo date('Y-m-d H:i:s', $sec) . substr($usec, 1);
Output 1 = 2016-07-12 16:27:08.56752900
This has worked for me and is a simple three-liner:
function udate($format='Y-m-d H:i:s.', $microtime=NULL) {
if(NULL === $microtime) $microtime = microtime();
list($microseconds,$unix_time) = explode(' ', $microtime);
return date($format,$unix_time) . array_pop(explode('.',$microseconds));
}
This, by 7 default (no params supplied) will return 6 a string in this format for the current 5 microsecond it was called:
YYYY-MM-DD HH:MM:SS.UUUUUUUU
An 4 even simpler/faster one (albeit, with only 3 half the precision) would be as follows:
function udate($format='Y-m-d H:i:s.', $microtime=NULL) {
if(NULL === $microtime) $microtime = microtime(true);
list($unix_time,$microseconds) = explode('.', $microtime);
return date($format,$unix_time) . $microseconds;
}
This 2 one would print out in the following format:
YYYY-MM-DD 1 HH:MM:SS.UUUU
time: String in a format accepted by strtotime(), defaults 5 to "now".
time: The string to parse, according 4 to the GNU » Date Input Formats syntax. Before 3 PHP 5.0.0, microseconds weren't allowed 2 in the time, since PHP 5.0.0 they are allowed 1 but ignored.
Working from Lucky's comment and this feature request in the PHP bug database, I use something 1 like this:
class ExtendedDateTime extends DateTime {
/**
* Returns new DateTime object. Adds microtime for "now" dates
* @param string $sTime
* @param DateTimeZone $oTimeZone
*/
public function __construct($sTime = 'now', DateTimeZone $oTimeZone = NULL) {
// check that constructor is called as current date/time
if (strtotime($sTime) == time()) {
$aMicrotime = explode(' ', microtime());
$sTime = date('Y-m-d H:i:s.' . $aMicrotime[0] * 1000000, $aMicrotime[1]);
}
// DateTime throws an Exception with a null TimeZone
if ($oTimeZone instanceof DateTimeZone) {
parent::__construct($sTime, $oTimeZone);
} else {
parent::__construct($sTime);
}
}
}
$oDate = new ExtendedDateTime();
echo $oDate->format('Y-m-d G:i:s.u');
Output:
2010-12-01 18:12:10.146625
How about this?
$micro_date = microtime();
$date_array = explode(" ",$micro_date);
$date = date("Y-m-d H:i:s",$date_array[1]);
echo "Date: $date:" . $date_array[0]."<br>";
Sample Output
2013-07-17 08:23:37:0.88862400
0
This should be the most flexible and precise:
function udate($format, $timestamp=null) {
if (!isset($timestamp)) $timestamp = microtime();
// microtime(true)
if (count($t = explode(" ", $timestamp)) == 1) {
list($timestamp, $usec) = explode(".", $timestamp);
$usec = "." . $usec;
}
// microtime (much more precise)
else {
$usec = $t[0];
$timestamp = $t[1];
}
// 7 decimal places for "u" is maximum
$date = new DateTime(date('Y-m-d H:i:s' . substr(sprintf('%.7f', $usec), 1), $timestamp));
return $date->format($format);
}
echo udate("Y-m-d\TH:i:s.u") . "\n";
echo udate("Y-m-d\TH:i:s.u", microtime(true)) . "\n";
echo udate("Y-m-d\TH:i:s.u", microtime()) . "\n";
/* returns:
2015-02-14T14:10:30.472647
2015-02-14T14:10:30.472700
2015-02-14T14:10:30.472749
*/
0
String in a format accepted by strtotime() It 1 work!
Inside of an application I am writing I 11 have the need to set/display microtime on 10 DateTime objects. It seems the only way 9 to get the DateTime object to recognize 8 microseconds is to initialize it with the 7 time in format of "YYYY-MM-DD HH:MM:SS.uuuuuu". The 6 space in between the date and time portions 5 can also be a "T" as is usual in ISO8601 4 format.
The following function returns a 3 DateTime object initialized to the local 2 timezone (code can be modified as needed 1 of course to suit individual needs):
// Return DateTime object including microtime for "now"
function dto_now()
{
list($usec, $sec) = explode(' ', microtime());
$usec = substr($usec, 2, 6);
$datetime_now = date('Y-m-d H:i:s\.', $sec).$usec;
return new DateTime($datetime_now, new DateTimeZone(date_default_timezone_get()));
}
PHP documentation clearly says "Note that date() will always generate 000000 since it takes an integer parameter...". If 2 you want a quick replacement for date()
function 1 use below function:
function date_with_micro($format, $timestamp = null) {
if (is_null($timestamp) || $timestamp === false) {
$timestamp = microtime(true);
}
$timestamp_int = (int) floor($timestamp);
$microseconds = (int) round(($timestamp - floor($timestamp)) * 1000000.0, 0);
$format_with_micro = str_replace("u", $microseconds, $format);
return date($format_with_micro, $timestamp_int);
}
(available as gist here: date_with_micro.php)
Building on Lucky’s comment, I wrote a simple 5 way to store messages on the server. In 4 the past I’ve used hashes and increments 3 to get unique file names, but the date with 2 micro-seconds works well for this application.
// Create a unique message ID using the time and microseconds
list($usec, $sec) = explode(" ", microtime());
$messageID = date("Y-m-d H:i:s ", $sec) . substr($usec, 2, 8);
$fname = "./Messages/$messageID";
$fp = fopen($fname, 'w');
This 1 is the name of the output file:
2015-05-07 12:03:17 65468400
Some answers make use of several timestamps, which 6 is conceptually wrong, and overlapping issues 5 may occur: seconds from 21:15:05.999
combined by microseconds 4 from 21:15:06.000
give 21:15:05.000
.
Apparently the simplest is to 3 use DateTime::createFromFormat()
with U.u
, but as stated in a comment, it fails if there are 2 no microseconds.
So, I'm suggesting this 1 code:
function udate($format, $time = null) {
if (!$time) {
$time = microtime(true);
}
// Avoid missing dot on full seconds: (string)42 and (string)42.000000 give '42'
$time = number_format($time, 6, '.', '');
return DateTime::createFromFormat('U.u', $time)->format($format);
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.