Carbon timestamp property returns wrong date millis - php

I'm trying to return a date parsed to the current server timezone (is stored in UTC) based on the day, the month and the year only. For that reason I have a function that looks like this:
private function getFormattedDate(string $stringDate): array
{
$date = Carbon::createFromFormat(
'Y-m-d',
$stringDate,
config('app.timezone')
);
return [
'date' => $date->timestamp,
'timezone' => $date->timezoneName,
];
}
The problem is that always the 'date' key in the array gets 1577113131 for example (and consecutive numbers each time I execute the method), so:
First execution: 1577113515
Second execution: 1577113525
Third execution: 1577113548
And so on...
Although the timestamp represents the right date in Y-m-d, the variation each time I execute the method shouldn't happen.
So, how can I solve this problem and get the timestamp in the millisecond? I have printed what's in the 'date' Carbon object and it seems to have the right date information:
^ Carbon\Carbon #1577113734 {#1048
#constructedObjectId: "00000000212d5614000000005c7c5f51"
#localMonthsOverflow: null
#localYearsOverflow: null
#localStrictModeEnabled: null
#localHumanDiffOptions: null
#localToStringFormat: null
#localSerializer: null
#localMacros: null
#localGenericMacros: null
#localFormatFunction: null
#localTranslator: null
#dumpProperties: array:3 []
#dumpLocale: null
date: 2019-12-23 10:08:54.0 America/Bogota (-05:00)
}
The expected output is:
'date' => 1577113734000,
'timezone' => 'America/Bogota'
Taking into account the date: 2019-12-23 10:08:54.0 America/Bogota (-05:00)

Lets try this, it should work for you
$format = 'Y-m-d';
$date = Carbon::createFromFormat($format, '2009-02-15');
$nowInMilliseconds = (int) ($date->timestamp . str_pad($date->milli, 3, '0', STR_PAD_LEFT));
echo $nowInMilliseconds;
And you can change your example like this:
private function getFormattedDate(string $stringDate): array
{
$date = Carbon::createFromFormat(
'Y-m-d',
$stringDate,
config('app.timezone')
);
$dateInMilliseconds = (int) ($date->timestamp . str_pad($date->milli, 3, '0', STR_PAD_LEFT));
return [
'date' => $dateInMilliseconds,
'timezone' => $date->timezoneName,
];
}

Use !:
$date = Carbon::createFromFormat(
'!Y-m-d',
$stringDate,
config('app.timezone')
);
https://www.php.net/manual/en/datetime.createfromformat.php
createFromFormat is a native PHP function and by default it takes current time (current value of units you don't specify), if ! prefix is used, it takes minimum value for each (so 0 for hours/minutes/seconds).

Related

Correct epoch to DateTime conversion

Whit this code:
$epoch= '1609455600';
$date = new DateTime( '#'.$epoch);
echo $date-> format( 'Y-m-d');
I see this result 2020-12-31. The server timezone is reported as Europe/Zurich (with date_default_timezone_get). But in this time zone that date should be 2021-1-1.
What is going on here?
In addition to the comment from #tuckbros. The output with var_export shows that the DateTime object has the time zone 00:00 (UTC).
date_default_timezone_set('Europe/Zurich');
$epoch= '1609455600';
$date = new DateTime( '#'.$epoch);
var_export($date);
/*
DateTime::__set_state(array(
'date' => '2020-12-31 23:00:00.000000',
'timezone_type' => 1,
'timezone' => '+00:00',
))
*/
The clean way to get the local time is to transfer the object to the desired time zone (and not to add any offset times).
$date->setTimeZone(new DateTimeZone(date_default_timezone_get()));
var_export($date);
/*
DateTime::__set_state(array(
'date' => '2021-01-01 00:00:00.000000',
'timezone_type' => 3,
'timezone' => 'Europe/Zurich',
))
*/
You can now continue to work with the DateTime object, since it has the correct time zone in addition to the correct local time.

Laravel set date as 1970 when the value is null

Sometimes laravel set date 1970 when the value is null, it's possibile save value as NULL instead 01-01-1970?
'start_date' => date('Y-m-d', strtotime($request->input('start_date'))),
'end_date' => $request->has('end_date') ? date('Y-m-d', strtotime($request->input('end_date'))) : NULL,
This code is not working.
How i can solve it?
According to this answer In Laravel 5.5+
$request->exists: Alias for $request->has
$request->has: Determine if the request contains a given input item
key.
$request->filled: Determine if the request contains a non-empty value
for an input item.
All you need - change has to filled:
'end_date' => $request->filled('end_date') ? date('Y-m-d H:i:s', strtotime($request->input('end_date'))) : NULL,
In MySQL if the date format is not complete or invalid it is set to the default.
Update your date function to include time, if you have a datetime field you must also pass a time.
date("Y-m-d H:i:s");
'start_date' => date('Y-m-d H:i:s', strtotime($request->input('start_date'))),
'end_date' => $request->has('end_date') ? date('Y-m-d H:i:s', strtotime($request->input('end_date'))) : NULL,
Please try the below code
Need to check whether request has available then convert to time
'start_date' =>$request->has('start_date') ? date('Y-m-d', strtotime($request->input('start_date'))) : NULL,
'end_date' => $request->has('end_date') ? date('Y-m-d', strtotime($request->input('end_date'))) : NULL,

Laravel Carbon does not consider timezone DST

Given my UsersTableSeeder.php class, I am seeding my database with fake data, using a loop:
$numberOfUsers = 150;
DB::table('users')->delete();
$faker = Faker::create();
for ($i = 1; $i <= $numberOfUsers; $i++) {
DB::table('users')->insert([
'id' => $i,
'firstName' => $faker->firstName,
'lastName' => $faker->lastName,
'email' => $faker->email,
'password' => bcrypt("123"),
'created_at' => Carbon::now()->addDays((-5 * $i) - 2)->format('Y-m-d H:i:s'),
'updated_at' => Carbon::now()->addDays(-5 * $i)->format('Y-m-d H:i:s'),
]);
}
The problem here is that when my datetime values are generated, there is a chance it might fall in a DST zone, like between 2017-03-12 02:00:00 and 2017-03-12 02:59:59 (which does happen) and it gives me the following error:
[PDOException]
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime value: '2016-03-13 02:08:11' for column 'created_at' at row 1
Now I understand that I cannot put such a value in my database, because my database is smart enough to know that this zone in time doesn't exactly exit. But is there any way I can 'make' Carbon smart enough to consider DST ? I do not want to manually check it with something like:
if ($my_date > 2017-03-12 02:00:00 && $my_date < 2017-03-12 02:59:59)
In Fact Carbon can handle DST zones.
$date = '2017-03-26 02:01:01';
$date = \Carbon\Carbon::parse($date, 'Europe/Berlin');
dd((string)$date);
Results in
// an extra hour was added automatically
"2017-03-26 03:01:01"
Per default Laravel uses 'UTC' for all date and datetime operations (including Carbon). This value can be set in app/config.php
If you actually want to your datetimes be considered in 'UTC' in database a dirty workaround could be something like that:
EDIT:
// calculate current offset to UTC:
$offset = \Carbon\Carbon::now('America/Montreal')->offsetHours;
'created_at' => Carbon::now('America/Montreal')->addHours(-4 + $i)->addDays((-1 * $i) - 2)->tz('UTC')->addHours($offset)->format('Y-m-d H:i:s')
You can generate your timestamps with Carbon and provide the timezone. Try just:
Carbon::now()->format('c')

Function doesn't come to the end

$time = time();
$foo = array(
1448319600 => array(
array(
'foo' => 'bar'
),
array(
'bar' => 'foo'
)
),
1448578800 => array(
array(
'foo2' => 'bar2'
),
array(
'bar2' => 'foo2'
)
)
);
function bar($time, $foo) {
$count = 0;
do {
$count++;
$time = strtotime('+1 day', $time);
} while (isset($foo[$time]) === false);
return array(
'count' => $count,
'foo' => $foo[$time]
);
}
bar($time, $foo);
It's loading and loading and loading, because isset($foo[$time]) === false always seems to be true. I just can't find the error.
(Some more text to be able to submit. Some more text to be able to submit. Some more text to be able to submit.)
strtotime('+1day') is going to use "now" , e.g. 3:35pm as the base time, so you're doing the equivalent of
$now = time(); // 1448400979
$tomorrow = strtotime('+1 day', $now); // 1448487379
while(!isset($arr[$tomorrow])) { ... }
Since that value is highly unlikely to ever be in your array as a key, your loop never ends. You need to do a >= comparison or something, to check when your currently-being-considered date becomes larger than any key in your array.
At the start of your script you are setting time to the current time. Then in your do while loop you are incrementing the time by one day each time it loops. isset($foo[time]) === false will only return false and exit the loop when your time started at exactly 11pm sometime before Mon, 23 Nov 2015 23:00:00 +0000 or Thu, 26 Nov 2015 23:00:00 +0000.
An example being the timestamp while writing this post is 1448401349 If I add one day to it I get 1448487749.
You might want to look into rounding your timestamps to midnight to make sure you get collisions in your loop that allow it to exit. unix timestamp round to midnight

PHP date() function inserting zeros into database

I have an array like so which has the column names of the table on the left and the associating values on the right.
$proceduredata = array
(
'patient_id' => $patientfk,
'name_id' => $procedurenamefk,
'department_id' => $departmentfk,
'dosage_id' => $dosagefk,
'edocument' => NULL, //not implemented yet
'user_id' => $this->session->userdata('userID'),
'duration' => NULL, //not implemented yet
'submitted' => date('d-m-Y H:i:s', now()),
'comment' => NULL, //to be implemented
);
This array is then passed into a SQL insert function. The insert works fine but my "Submitted" column is getting values of this only:
0000-00-00 00:00:00
I made sure the time formats are matching? Is there something I have missed thanks.
change the date format
submitted' => date('Y-m-d H:i:s', now())
I believe that the "now()" function is a sql function and you are using PHP with the "date()" funciton. Try changing "now()" to "time()" which will give you a proper unix timestamp that the "date()" function can use to create a properly formatted date.
EDIT: I just realized I am not familiar with codeignighter, so please excuse me if the "now()" function is part of that framework.
now() is not a function, change now() to time(). Alternatively, date()'s second paramater is optional if you omit it date automatically uses the current date/time:
echo date('d-m-Y H:i:s');
will echo the current date/time in the format requested.

Categories