Laravel - dateformat validation not working as expected - php

My code:
$data['from'] = '2020-03-20 20:30:00';
$data['to'] = '2020-03-21 00:45:00';
$validity = \Validator::make($data, [
'from' => ['date_format:Y-m-d H:i:s'],
'to' => ['date_format:Y-m-d H:i:s']
]);
// This if gets true, and the error message is:
The to does not match the format Y-m-d H:i:s
if($validity->fails()) {
dd($validity->errors());
}
and amazingly when I change 00:45:00 to 01:45:00 it doesn't get inside that if. How can I fix it?

Since your locale is set up to be Asia/Tehran the time 2020-03-21 00:45:00 is actually not valid. According to https://www.timeanddate.com/time/change/iran/tehran:
Saturday, 21 March 2020, 00:00:00 clocks are turned forward 1 hour to
Saturday, 21 March 2020, 01:00:00 local daylight time instead.
This means that times between 00:00:00 and 01:00:00 never occur. Since the Laravel date validator internally uses PHP's date parsing then that parsing fails and the error is raised. If you want to check only if a date is a given format ignoring any daylight savings quirks then you can use date_default_timezone_set to temporarily set the locale to one that does not observe daylight savings.

Try
$validity = \Validator::make($data, [
'from' => 'date_format:Y-m-d H:i:s',
'to' => 'date_format:Y-m-d H:i:s'
]);

Related

Laravel 8 with Backpack - datetime formatting on the frontend?

I am currently trying to format a datetime object that I access like this:
Blade:
{{ $event->start }} and {{ $event->end}}
this outputs something like this on the frontend blades:
2021-12-02 22:30:00 ($event->start) 2021-2021-12-02 23:00:00 ($event->end)
the formatting above is also how it is stored as a DATETIME object in the database.
Because I use other elements, like a fullcalendar, I dont want to change the way the database stores the dates, just formatting the dates on the frontend/controller directly.
Controller:
if ($course == 'course') {
$view = 'pages.course.current_course';
$id = '8';
}
// get the course data from the database
$events = DB::table('eventaries')
// map the current view $id to the database query
->where('category', $id)
// check if event is expired
->where('start', '>', now())
->get();
// pass through the data to the correct views
return view($view, [
"events" => $events
]);
But I need the following formatting: Sunday. 12th December 2021, 22:30 ($event->start) and 23:00 ($event->end)
I already got the formatting in the BackPack Backend right by adding 'format' => to the CrudController, like this:
CrudController:
CRUD::addColumn([
'name' => 'start',
'label' => 'Start',
'type' => 'datetime',
'format' => 'DD.MM.Y - H:mm',
]);
CRUD::addColumn([
'name' => 'end',
'label' => 'End',
'type' => 'datetime',
'format' => 'DD.MM.Y - H:mm',
]);
If you have Model defined for that particular table. you can define accessor for those two column, like
public function getStartAttribute($value)
{
return Carbon::parse($value)->toDayDateTimeString();
}
It will return output something like Mon, Nov 29, 2021 05:45 PM
Define these type of function for end column.
Refer this Carbon Document for other format and date operation
If you don't have Model you can use Carbon class in blade or controller directly
We will use createFromFormat() and format(), createFromFormat() will take two argument first give format of date and second one date and format() take one argument give formate as you want. you can see bellow examples:
Example 1:
$post->created_at->format('d-m-Y');
Example 2:
\Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $date)->format('d-m-Y')

Laravel date_format Validation Fails on Textual Month

My JavaScript library datepicker returns dates in a format "March 2019."
Carbon can decode it.
$date = Carbon::createFromFormat('M Y', $request->month);
Laravel fails on date_format validation.
$request->validate([
'month' => [
'required',
'date_format:M Y',
],
]);
saying
The month does not match the format M Y.
I have tried all PHP date formats from here
: M, MM, mm, m.
$request->validate([
'month' => [
'required',
'date_format:F Y',
],
]);
You're using the wrong format. You need to use standard PHP formats, which is what Carbon and Laravel's validation uses. You can find them in the PHP Docs for date()
So change your rule to:
date_format:"F Y"

Yii2: display dates in user time zone

In my DB I store all datetime fields in UTC format. Also, I have the ability to change default time zone by users. Each user can have own time zone, different from UTC.
How shall I display all model datetime fields in this case?
I have an idea. To do this action for each ActiveRecord model:
public function init()
{
parent::init();
$this->on(ActiveRecord::EVENT_AFTER_FIND, function($event) {
$this->created_date = (new \DateTime('now', new \DateTimeZone("Europe/Kiev")))->format("Y-m-d H:i:s");
});
}
But I'm not sure it's the best way for big amount of models...
if the dates are stored in UTC why not append the string UTC along the time and display it
$time = strtotime($this->created_at.' UTC');
date("Y-m-d H:i:s", $time);
Your code will look like this
public function init()
{
parent::init();
$this->on(ActiveRecord::EVENT_AFTER_FIND, function($event) {
$time = strtotime($model->create_at.' UTC');
$this->created_date = date("Y-m-d H:i:s", $time);
});
}
if I would do it I would just create a separate Helper and use it to display the date in the local format rather than EVENT_AFTER_FIND
Another alternative is to use this Extension
Search for frontend/config/main.php
Try putting in
return [
...
'components' => [
...
a FORMATTER part like
'formatter' => [
'dateFormat' => 'dd/MM/yyyy',
'datetimeFormat' => 'dd/MM/yyyy H:i:s',
'timeFormat' => 'H:i:s',
'locale' => 'it-IT',
'decimalSeparator' => ',',
'thousandSeparator' => '.',
'currencyCode' => 'EUR',
'numberFormatterSymbols' => [
NumberFormatter::CURRENCY_SYMBOL => '€',
],
'timeZone' => 'Europe/Rome',
],
Set your parameters like TimeZone, Currency, etc...
NB: I dont remember but maybe the NumberFormatter part need some other setup so delete the numberFormatterSymbols part if it give to you an error

Timezone in Yii2

My computer time zone 'Asia/Tashkent'. And I set Yii2 time zone to 'Asia/Tashkent' too in config. But Yii2 is still displaying time incorrectly. I am wondering what I have missed?
$time = date("Y-m-d H:i:s", time());
echo $time; // 2018-03-07 14:10:57
echo Yii::$app->formatter->asTime($time, 'medium'); // 7:10:57 PM
echo Yii::$app->formatter->asDate($time, 'medium'); // Mar 7, 2018
echo date_default_timezone_get(); // Asia/Tashkent
If you are giving asTime() string date formatter assumes it's in default timezone which by default in Yii 2 is UTC.
If you want this to be the same as the output of PHP date() change the default timezone in Yii to yours. For example in the configuration:
'components' => [
'formatter' => [
'class' => 'yii\i18n\Formatter',
'defaultTimeZone' => 'Asia/Tashkent',
],
],

SYMFONY Form TimeType use 1970-01-01 as default date, what is the value to set in the constraint GreaterThanOrEqual?

I have a TimeType field in a Symfony form. In the form AbstractType extended class the field looks like this:
$form->add('fieldTime', TimeType::class, array(
'label' => myLabel,
'constraints'=>array(
new GreaterThanOrEqual(array('value'=>date('H:i'))),
new Time()
),
);
The problem is that date('H:i') set as value to compare in the constraint GreaterThanOrEqual, pick up the actual date like: 2016-02-14 10:15:00.
Whereas the value received on the Submit is like this:
DateTime {#12481 ▼
+"date": "1970-01-01 11:00:00.000000"
+"timezone_type": 3
+"timezone": "Europe/Paris"
}
As you see, it has the time selected by the user but with the 1970 date, hence the constraint is always false.
I wonder how to either:
Pass in the constraint GreaterThanOrEqual value a time with the
1970-01-01 date but with the actual time;
Or how to use the default today date with the time submitted by the user thru the form?
You can pass "today" to GreaterThanOrEqual, and use a new DateTime() to get the complete date, not just the time of the day:
$form->add('fieldTime', TimeType::class, array(
'label' => myLabel,
'constraints'=>array(
new GreaterThanOrEqual("today")
),
'data' => new DateTime(),
);
Note that "today" is using the server's configured timezone. If you want to specify it, append it to the date string, i.e. "today UTC"

Categories