I am using cakePHP time format to change a date to the users timezone. Then I wish to check if it is today. When I pass $currentDate into $this->Time->isToday I get nothing back, even thought it is todays date.
If I pass in date("d/m/Y"); it works fine.
I have tried stringToTime also.
$currentDate = $this->Time->format(
'd/m/Y',
$message['Message']['created'],
null,
$userData['time_zone']
);
if($this->Time->isToday($currentDate)){
echo "today";
};
This is the fix I have implemented.
if($this->Time->isToday($message['Message']['created'], $userData['time_zone'])){
echo '<li class="conversation-divider"><span>Conversation started Toady</span></li>';
} else {
echo '<li class="conversation-divider"><span>Conversation started at '.$messageDate.'</span></li>';
};
According to the CakePHP book, you can pass timezone to the 'isToday()' method:
TimeHelper::isToday($dateString, $timezone = NULL)
So - try this:
$today = $this->Time->isToday(
$message['Message']['created'],
$userData['time_zone']
);
Did you make the timezone helper aware of the timezone you used in format()?
You need to at least once set timezone($timezone) for it to know it.
See https://github.com/cakephp/cakephp/blob/master/lib/Cake/Utility/CakeTime.php#L272
Related
I recently updated an old laravel 5.7 project to 8.0 and the created_at and updated_at model timestamps get created with the wrong format. Back in the day i used this code in all models that are from a SQL Server database to get it working between my local and production environment.
public function getDateFormat()
{
if (PHP_OS_FAMILY == 'Windows') {
return 'Y-d-m H:i:s.v';
} else {
return 'Y-m-d H:i:s';
}
}
I use windows to develop the application and a Linux server to run it with apache, but after updating the project the timestamps invert the day and month of the date. For example, if i create a model in the date '2022-06-07 13:00:00' the created_at timestamp will be '2022-07-06 13:00:00'.
Of course, changing the getDateFormat() method to only return 'Y-d-m H:i:s.v' in all environments works, but create another problem with php date function, for example, if i call <p> updated at: {{ date('d/m/Y H:i:s', strtotime($model->updated_at)) }}</p> the desired result would be updated at: 07/06/2022 13:00:00 but instead i get updated at: 06/07/2022 13:00:00.
I really dont know if this is a php timezone issue or something related to laravel, since the problem shows at saving/updating rows or displaying formatted data information.
try
date("Y-d-m H:i:s", time());
Please use:
updated at: {{ date('m/d/Y H:i:s', strtotime($model->updated_at)) }}
for the desired result as the above m shows month, d shows days similarly y shows year.
Laravel have Carbon so use it for datetime stuff
use Carbon\Carbon;
...
if(! function_exists('format_date') {
function format_date(string $date): string
{
return Carbon::parse($date)->format('d-m-Y H:i:s');
// something like 31-12-2022 12:00:00, just change format as you need
}
}
From your view:
{{ format_date($model->date) }}
Make sure to check Ref
On my Laravel app, I have created an AJAX call to search bookings based on a given name. In the database, every booking contains a date field. For some reason, the date I receive from my controller query is always the day before. So for example, when the date field in the database shows '2021-05-18', the collected date from the query shows '2021-05-17'.
Does anyone have an idea what can be the cause of this and how I can solve it?
I use the same date field in other controller functions and on other views as well, and there the date field is displaying correctly.
Also, in my config > app file I have set the 'timezone' to 'Europe/Brussels'.
A screenshot of my database:
The code in my controller is as follows:
public function searchReservation(Request $request)
{
$users = User::where('name', 'LIKE', '%'.$request->name.'%')
->select('id', 'name')
->get();
foreach($users as $user) {
$user['reservations'] = Booking::where('user_id', $user['id'])->get();
}
return $users;
}
My code in the controller, where I 'transform' the date, before I create a new booking:
if (Carbon::hasFormat($request->date, 'd-m-Y')) {
$request->date = Carbon::createFromFormat("d-m-Y", $request->date);
} else {
$request->date = Carbon::createFromFormat("d-n-Y", $request->date);
}
A screenshot of my database output, where the date is always a day before the real date:
When you are using Carbon for formatting a time, you need to explicitly set the time zone if you intend to process with a time zone other than UTC. Default values like created_at will be automatically saved properly by Laravel respecting the timezone set in config/app.php. For other date/time column you need to explicitly set the timezone for formatting with Carbon. Therefore, your code should be like:
if (Carbon::hasFormat($request->date, 'd-m-Y'))
{ $request->date = Carbon::createFromFormat("d-m-Y", $request->date, config('app.timezone')); //pass timezone value from config as the third parameter
}
else {
$request->date = Carbon::createFromFormat("d-n-Y", $request->date,config('app.timezone'));
}
I have a
As a scope I have: $scope.getDatetime = new Date();
And I wanna make the following work:
<span ng-show="getDatetime > foobar.datetime">Foobar</span>
The foobar.datetime is from ng-repeat with the format of: 2014-08-20 01:45:15
So I only wanna show that element, when current time is bigger then the datetime given.
Thought it was a easy as my example above, but it isn't - and I can't figure out if it's even possible without using plugins.
If I'm reading this correctly, then your issue is that your comparing a string and a date object. Try:
<span ng-show="getDatetime > getDate(foobar.datetime)">Foobar</span>
And in your javascript:
$scope.getDate = function(date) {
return new Date(date);
}
You need to convert your date to a timestamp, then you can compare the 2 dates, perhaps try using a filter to convert to a time stamp.
Recently I updated CakePHP from 2.3.9 to 2.4.4. As far as I remember (I can't test now) Timehelper::timeAgoInWords was working well in old CakePHP. But after this update I get locale problem. I change language to English, but time ago still comes in Turkish.
In core.php i already set default language to Turkish:
Configure::write('Config.language', 'tur');
Inside my view file I use this:
$d = "2012-05-02 20:17:30"
$myString = $this->Time->timeAgoInWords($d, array('end' => '+10 year'));
I get result in Turkish like this:
1 yıl, 8 ay, 4 hafta önce
I want result like this:
1 year, 8 months, 4 weeks ago
My session variables like this:
[Config] => Array
(
[userAgent] => 35db889a82essb4e57b540d52e8a766d
[time] => 1391121684
[countdown] => 10
[language] => eng
)
Although I set my language as English, result cames in Turkish. How can I debug/fix this ?
Edit:
I checked for Configure-language values. Results like this:
echo Configure::read( 'Config.language' );
result: tur
But
echo $this->Session->read('Config.language');
result: eng
As I noted in the top of my question, I already setted Configure::language inside my core.php file. Does core.php overrides my session value ?
Edit2:
And strange thing is, although Config.language looks like both "tur" and "eng", other parts inside my view file works well. For example this works well:
__("string")
Edit3:
Regarding to this page: http://book.cakephp.org/2.0/en/core-libraries/internationalization-and-localization.html
I added this:
class AppController extends Controller {
public function beforeFilter() {
if ($this->Session->check('Config.language')) {
Configure::write('Config.language', $this->Session->read('Config.language'));
}
}
}
After this change config language results like this:
echo Configure::read( 'Config.language' );
result: eng
echo $this->Session->read('Config.language');
result: eng
But I still see timeAgo result in Turkish..
Last week I migrated to new server, maybe some setting is missing for English or etc ? I can't understand why timeAgo doesn't work while __("string") works.
Edit4:
I even changed core.php like this:
Configure::write('Config.language', 'eng');
setlocale( LC_TIME, 'en_US.utf8', 'eng', 'en', 'en_US', 'en_UK' );
It seems like, in my configuration nothing changes timeAgoInWords's language. I override in every beforeFilter to change Config.language is to english, but still words are Turkish. Note that in my php.ini timezone is like this:
date.timezone = Europe/Istanbul
Edit5:
It seems like there is a problem in the translations. I checked for source code of timeago, here is a copy: https://github.com/cakephp/cakephp/blob/2.4.4/lib/Cake/Utility/CakeTime.php#L738
It seems like this method uses __d and __dn so I checked the results in my code. "az önce" means "just now" in Turkish.
I'm sure that Config.language is "eng". So:
echo __d('cake', 'just now', 'just now'); // results: "az önce"
echo __('just now'); // results: "just now"
echo __('az önce'); // results: "az önce"
$days=12;
echo __dn('cake', '%d day', '%d days', $days, $days); // results: "12 gün"
echo __('gün'); // results: "days"
To debug echo Configure::read( 'Config.language' ); right before your timeAgo call. If you find it's not "eng" then you are setting the language to English after timeAgo was already called.
IF that does not work then you may have to call setlocale as well
I use this for english dates:
setlocale( LC_TIME, 'en_US.utf8', 'eng', 'en', 'en_US', 'en_UK' );
And I guess this would the call for Turkish
setlocale(LC_TIME, 'tr_TR.UTF-8', 'tr_TR', 'tr', 'turkish');
PS: Looking at the history of the TimeHelper nothing was changed to affect the locale, but may a dependency was changed.
Normally I change current language like this:
$this->Session->write('Config.language', $lang);
I set default language like this in every request in core.php:
Configure::write('Config.language', 'tur');
Regarding to CakePHP documents I must add this code to my AppController:
class AppController extends Controller {
public function beforeFilter() {
if ($this->Session->check('Config.language')) {
Configure::write('Config.language', $this->Session->read('Config.language'));
}
}
}
After adding the code above to beforeFilter() of AppController, I refreshed /tmp/cache/persistent/ folder and everything works fine.
Edit:
This solution worked well for english but it didn't work for other languages.
Why ? As noted in this question cake looks for cake.po files inside your Locale folder.
For example if you want to see cake's messages in french, so you need to create this file:
/app/Locale/fra/LC_MESSAGES/cake.po
Where do CakePHP use cake.po records ?
For example: this method
You can create default po files like this: i18n shell tutorial
After shell's file creation, you can edit cake.po file for your language.
For some languages cake.po files are ready. For example: french file
You can find rest from there: https://github.com/cakephp/localized
For Russian language it`s necessary to set cake.po file encoding to utf-8, or you will see blank options instead of translated month names.
My solution is:
1. Place file cake.po in \app\Locale\rus\LC_MESSAGES directory and set
2. in AppController file
public function beforeFilter()
{
Configure::write('Config.language', 'rus');
}
Translation file for your language you can find in files of CakePHP Localized plugin https://github.com/cakephp/localized
I store all dates in UTC in my database. Cakephp runs in UTC and communicates with mysql in UTC. Now i have following scenario:
debug(CakeTime::format('Y-m-d H:i', '2013-03-22 03:00', false,
new DateTimeZone('Europe/Berlin')));
//output is 2013-03-22 04:00
debug(CakeTime::format('Y-m-d H:i', '2013-04-05 03:00', false,
new DateTimeZone('Europe/Berlin')));
//output is 2013-04-05 05:00
As you can see CakeTime added 2 hours of offset in the second example, i guess that is because it considers DST (starting at 31.03.2013).
However what i am trying to do is displaying recurring events in a calendar and this event starts each second Friday at 4am - always, even in summer. Therefore the calendar may not display it to be at 5am!
/EDIT: the first example is corret. the event has to be at 4am. but also in summer
I solved the problem using these two functions for time converting.
Keep in mind that this is for recurring events, that start always at the same time of day(e.g. 4am) regardless of DST.
public function dateTimeToSever($date, $user_timezone) {
$DateTime = new DateTime($date, $user_timezone);
$dst = $DateTime->format('I');
$toServerDateTime = CakeTime::toServer($date, $user_timezone, 'Y-m-d H:i');
if ($dst) {
$toServerDateTime = date('Y-m-d H:i', strtotime($toServerDateTime . ' + 1 Hours'));
}
return $toServerDateTime;
}
public function dateTimeToUser($date, $user_timezone) {
$DateTime = new DateTime($date, new DateTimeZone('UTC'));
$DateTime->setTimezone($user_timezone);
$dst = $DateTime->format('I');
$userDateTime = CakeTime::format('Y-m-d H:i', $date, false, $user_timezone);
if ($dst) {
$userDateTime = date('Y-m-d H:i', strtotime($userDateTime . ' - 1 Hours'));
}
return $userDateTime;
}
This should work for all timezones that use positive DST. AFAIK some timezones, e.g. somewhere in North India, have some kind of negative timezone. I guess in that case the "+ 1 Hours" has to become "- 1 Hours" and vice versa.
In your example you are getting the wrong time in both cases. If you want to store all your dates in UTC then you need to make sure you store the correct UTC values for the timezone the user is in. For example, if you want a reoccurring event every Friday at 3pm in the Europe/Berlin timezone, then do the following.
// save your date like this
$date = new DateTime('2013-04-05 03:00', new DateTimeZone('Europe/Berlin'));
$utc = $date->getTimestamp();
// print them correctly like this
$utc = CakeTime::format('Y-m-d H:i', $utc, false, new DateTimeZone('Europe/Berlin'));
On caveat to this approach, if a user changes their timezone from one with DST to one without (or vice-versa), they may encounter the same problem.