Coder Social home page Coder Social logo

laravel-timezone's Introduction

Laravel Timezone

Latest Version on Packagist Total Downloads Licence Quality Score StyleCI Buy us a tree Treeware (Trees)

An easy way to set a timezone for a user in your application and then show date/times to them in their local timezone.

How does it work

This package listens for the \Illuminate\Auth\Events\Login event and will then automatically set a timezone on your user model (stored in the database).

This package uses the torann/geoip package which looks up the users location based on their IP address. The package also returns information like the users currency and users timezone. You can configure this package separately if you require.

How to use

You can show dates to your user in their timezone by using

{{ Timezone::convertToLocal($post->created_at) }}

Or use our nice blade directive

@displayDate($post->created_at)

More examples below

Installation

Pull in the package using Composer

composer require jamesmills/laravel-timezone

Publish database migrations

php artisan vendor:publish --provider="JamesMills\LaravelTimezone\LaravelTimezoneServiceProvider" --tag=migrations

Run the database migrations. This will add a timezone column to your users table.

php artisan migrate

Examples

Showing date/time to the user in their timezone

Default will use the format jS F Y g:i:a and will not show the timezone

{{ Timezone::convertToLocal($post->created_at) }}

// 4th July 2018 3:32:am

If you wish you can set a custom format and also include a nice version of the timezone

{{ Timezone::convertToLocal($post->created_at, 'Y-m-d g:i', true) }}

// 2018-07-04 3:32 New York, America

Using blade directive

Making your life easier one small step at a time

@displayDate($post->created_at)

// 4th July 2018 3:32:am

And with custom formatting

@displayDate($post->created_at, 'Y-m-d g:i', true)

// 2018-07-04 3:32 New York, America

Saving the users input to the database in UTC

This will take a date/time, set it to the users timezone then return it as UTC in a Carbon instance.

$post = Post::create([
    'publish_at' => Timezone::convertFromLocal($request->get('publish_at')),
    'description' => $request->input('description'),
]);

Custom Configuration

Publishing the config file is optional.

php artisan vendor:publish --provider="JamesMills\LaravelTimezone\LaravelTimezoneServiceProvider" --tag=config

Flash Messages

When the timezone has been set, we display a flash message, By default, is configured to use Laravel default flash messaging, here are some of the optional integrations.

laracasts/flash - 'flash' => 'laracasts'

mercuryseries/flashy - 'flash' => 'mercuryseries'

spatie/laravel-flash - 'flash' => 'spatie'

mckenziearts/laravel-notify - 'flash' => 'mckenziearts'

usernotnull/tall-toasts - 'flash' => 'tall-toasts'

To override this configuration, you just need to change the flash property inside the configuration file config/timezone.php for the desired package. You can disable flash messages by setting 'flash' => 'off'.

Overwrite existing timezones in the database

By default, the timezone will be overwritten at each login with the current user timezone. This behavior can be restricted to only update the timezone if it is blank by setting the 'overwrite' => false, config option.

Default Format

By default, the date format will be jS F Y g:i:a. To override this configuration, you just need to change the format property inside the configuration file config/timezone.php for the desired format.

Lookup Array

This lookup array configuration makes it possible to find the remote address of the user in any attribute inside the Laravel request helper, by any key. Having in mind when the key is found inside the attribute, that key will be used. By default, we use the server attribute with the key REMOTE_ADDR. To override this configuration, you just need to change the lookup property inside the configuration file config/timezone.php for the desired lookup.

User Message

You may configure the message shown to the user when the timezone is set by changing the message property inside the configuration file config/timezone.php

Underlying GeoIp Package

If you wish to customise the underlying torann/geoip package you can publish the config file by using the command below.

php artisan vendor:publish --provider="Torann\GeoIP\GeoIPServiceProvider" --tag=config

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

License

This package is 100% free and open-source, under the MIT license. Use it however you want.

This package is Treeware. If you use it in production, then we ask that you buy the world a tree to thank us for our work. By contributing to the Treeware forest you’ll be creating employment for local families and restoring wildlife habitats.

Issues

If you receive a message like This cache store does not support tagging this is because the torann/geoip package requires a caching driver which supports tagging and you probably have your application set to use the file cache driver. You can publish the config file for the torann/geoip package and set 'cache_tags' => null, to solve this. Read more about this issue here.

laravel-timezone's People

Contributors

aldesrahim avatar amandiobm avatar amayer5125 avatar bastinald avatar devnll avatar ecointest avatar gpasztor87 avatar grantholle avatar jamesmills avatar laravel-shift avatar maher1337 avatar micahhenshaw avatar oddvalue avatar samtlewis avatar usernotnull avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-timezone's Issues

UpdateUsersTimezone gives wrong info

Hi,

Thanks for this nice package,
I've integrated it on live server, and I'm using ipgeolocation service in geoip package config.
So, I found this bug here :

if (config('timezone.overwrite') == true || $user->timezone == null) {
                $user->timezone = $geoip_info['timezone'];
                $user->save();
                $this->notify($geoip_info);
 }

This : $geoip_info['timezone'] returns Null
Here dd($geoip_info) (See Attached)
So to fix it :
` $user->timezone = $geoip_info->time_zone['name'];

bug
`

Thanks.

Laravel 10 issue...

Hello, when trying to run composer install/update with Laravel 10, I get these errors:

- Root composer.json requires jamesmills/laravel-timezone ^1.12 -> satisfiable by jamesmills/laravel-timezone[1.12.0].

- jamesmills/laravel-timezone 1.12.0 requires treeware/plant dev-main -> found treeware/plant[dev-main] but it does not match your minimum-stability.

[Hot-Fix]: Null as first param on convertToLocal method.

At Timezone::convertToLocal has an if statement which checks if the date is not null. That statement is never reached because the method signature required the first param to be a Carbon Object.

I had sometimes my date are null which broke the @displayDate directive.

Argument 1 passed to JamesMills\LaravelTimezone\Timezone::convertToLocal() error

Hello,

When using the following:

{{ Timezone::convertToLocal(auth()->user()->created_at) }}

I get the desired output in my view, even when I use updated_at. However if I change the created_at to last_login like so:

{{ Timezone::convertToLocal(auth()->user()->last_login) }}

I get the following error:

Argument 1 passed to JamesMills\LaravelTimezone\Timezone::convertToLocal() must be an instance of Carbon\Carbon or null, string given, called in C:\laragon\www\stylistrater\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php on line 261 (View: C:\laragon\www\stylistrater\resources\views\home.blade.php)

All are datatype TIMESTAMP and are being updated using Laravel's default now() function.

        `last_login` TIMESTAMP NULL DEFAULT NULL,
	`last_login_ip` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
	`timezone` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
	`created_at` TIMESTAMP NULL DEFAULT NULL,
	`updated_at` TIMESTAMP NULL DEFAULT NULL,

Anyone else having this issue? Not sure why it works fine on the other TIMESTAMP entries but not others.

Any help with this would be greatly appreciated.

Regards,
RJ

You have to publish config to use package

We say it's optional to publish the config but it's not. If you use the package without the config published it cannot get the default config('timezone.lookup').

foreach (config('timezone.lookup') as $type => $keys) {

Not sure if we are doing something wrong with using default values?

Add timezone select to Jetstream profile page?

Is there any way to add a timezone select to the Jetstream profile page? I only want to set timezone automatically when the user first log in and then let them change it under profile settings.

Has anyone built a select like that? I tried to add one, but quickly added up deep in laravel/jetstream core folders and figured I better ask here first.

Thanks!

Always saving default timezone on localhost.

Hi!

User timezone value are always been saved as 'America/New_York', or wathever the default timezon in geoip config is.

It is because i'm on localhost? Or maybe I've missed something during installation?

Thanks in advance!

api user update

i am using laravel passport and the package not update the user time zone in database

Daylight savings (CET vs CEST?)

Hi there,

First off wonderful package thank you for your awesome contribution :)

I'm confused as to why @displayDate($event->event_date) is returning a time in CEST right now for a user in 'Europe/Paris' when we're not yet in CEST.

The date time on the environment is accurately showing March 16 2021, so not an env issue.

Is something that needs to be toggled manually?

Make database migration publishable

It would be very useful to make the included migration publishable and to use current date for filename.
I am having issues with your package trying to update users table that has not yet been created.

Can't install laravel-timezone package

This is not an issue but i think you should make the docs more clear.

Something like requirement of Laravel version, PHP version.

I use Laravel 5.4 and can't install the package.

Invalid argument supplied for foreach()

Hello!

Installed as shown, but once i Login i Get the message "Invalid argument supplied for foreach()".

here:

        /**

    * @return mixed

    */

    private function getFromLookup()

    {

        $result = null;

 

        foreach (config('timezone.lookup') as $type => $keys) {

            if (empty($keys)) {

                continue;

            }

 

            $result = $this->lookup($type, $keys);

 

            if (is_null($result)) {

                continue;

            }

        }

 

        return $result;

    }

 

    /**

Laravel 10 future support.

Hi James

Right now if a new data is declared with protected $dates it gets converted with base timezone helper.

The new docs have changed this:

`Model "Dates" Property
Likelihood Of Impact: Medium

The Eloquent model's deprecated $dates property has been removed. Your application should now use the $casts property:

protected $casts = [
'deployed_at' => 'datetime',
];`

Will it still work as intended?

Thanks

Formatting dates

Hello, is it possible to get the format date for each country ? I'm not sure if the APIs return information connected to date format each country.

Usage of protected instead of private function

private function formatTimezone(Carbon $date) : string

I'm wondering, if we can use protected instead of private function then people can easily extends the Timezone and customize to their need.

Also, Can we extract the obtaining of the time zone in another class which will be responsible for assigning the time zone to the user (the user could be passed in the constructor and if not then we will use the Auth::user() )?

This will allow us to assign the time zone to the user without necessarily listening to the authentication event.

$ip = $this->getFromLookup();

Crashing Passport

When I installed this package, laravel passport authentication stopped working

Not setting TimeZone

I just installed to Laravel 5.6 and the time zone is not being set to the Users Table.
Timezone field is in the database (confirmed)

User logs into 'App\Http\Controllers\Auth' @ 'LoginController' using method 'login'

Login goes fine, but the timezone field is never filled.

Even added \Log::info('handle login timezone called'); inside the UpdateUsersTimezone to see if its catching the event

public function handle(Login $event)
    {
        \Log::info('handle login timezone called');
        $geoip_info = geoip()->getLocation(request()->server->get('REMOTE_ADDR', null));

        if (auth()->user()->timezone != $geoip_info['timezone']) {
            $user = auth()->user();
            $user->timezone = $geoip_info['timezone'];
            $user->save();

            if (config('timezone.flash') == 'laracasts') {
                flash()->success('We have set your timezone to ' . $geoip_info['timezone']);
            } else {
                request()->session()->flash('success', 'We have set your timezone to ' . $geoip_info['timezone']);
            }
        }
    }

But no go.

I am not using the default Auth Login that comes with Laravel, so I am sure that is the main problem since that event is never fired 'use Illuminate\Auth\Events\Login;'

Any suggestions?
Thanks,

Dave

Issue with require

Problem 1
- jamesmills/laravel-timezone[dev-master, 1.12.0, ..., 1.13.0] require torann/geoip ^3.0 -> satisfiable by torann/geoip[3.0.1, 3.0.2, 3.0.3, 3.0.4].
- jamesmills/laravel-timezone[dev-pullrequests/keenminded/forked, dev-pullrequests/jonnymccullagh/diffForHumans, 1.9.3, ..., 1.10.0] require laravel/framework 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 -> found laravel/framework[v5.6.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but it conflicts with your root composer.json require (^10.0).
- jamesmills/laravel-timezone dev-laravel-8-security-updates requires laravel/framework 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8.24.0 -> found laravel/framework[v5.6.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.24.0, ..., 8.x-dev] but it conflicts with your root composer.json require (^10.0).
- jamesmills/laravel-timezone[1.0.0, ..., 1.0.4] require illuminate/auth ^5.6 -> found illuminate/auth[v5.6.0, ..., 5.8.x-dev] but these were not loaded, likely because it conflicts with another require.
- jamesmills/laravel-timezone[1.0.5, ..., 1.0.6] require illuminate/auth 5.6.* -> found illuminate/auth[v5.6.0, ..., 5.6.x-dev] but these were not loaded, likely because it conflicts with another require.
- jamesmills/laravel-timezone[1.1.0, ..., 1.2.1] require laravel/framework 5.6.* || 5.7.* || 5.8.* -> found laravel/framework[v5.6.0, ..., 5.8.x-dev] but it conflicts with your root composer.json require (^10.0).
- jamesmills/laravel-timezone[1.3.0, ..., 1.8.1] require laravel/framework 5.6.* || 5.7.* || 5.8.* || ^6 -> found laravel/framework[v5.6.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev] but it conflicts with your root composer.json require (^10.0).
- jamesmills/laravel-timezone[1.9.0, ..., 1.9.2] require laravel/framework 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 -> found laravel/framework[v5.6.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev] but it conflicts with your root composer.json require (^10.0).
- jamesmills/laravel-timezone 1.11.0 requires laravel/framework 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 -> found laravel/framework[v5.6.0, ..., 5.8.x-dev, v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev, v9.0.0-beta.1, ..., 9.x-dev] but it conflicts with your root composer.json require (^10.0).
- torann/geoip 3.0.1 requires php ^7.2 -> your php version (8.2.2) does not satisfy that requirement.
- torann/geoip[3.0.2, ..., 3.0.3] require illuminate/support ^8.0 -> found illuminate/support[v8.0.0, ..., 8.x-dev] but these were not loaded, likely because it conflicts with another require.
- torann/geoip 3.0.4 requires illuminate/cache ^8.0|^9.0 -> found illuminate/cache[v8.0.0, ..., 8.x-dev, v9.0.0-beta.1, ..., 9.x-dev] but these were not loaded, likely because it conflicts with another require.
- Root composer.json requires jamesmills/laravel-timezone * -> satisfiable by jamesmills/laravel-timezone[dev-master, dev-laravel-8-security-updates, dev-pullrequests/jonnymccullagh/diffForHumans, dev-pullrequests/keenminded/forked, 1.0.0, ..., 1.13.0, 9999999-dev].

Inertia support

Hello

Thinking about using this package for our timezones.

Do you know if it works we with inertia / vue js?

Use language files

Noticed a recent change allowing config for a message. Maybe in v2, use publishable language files for this and other strings where possible.

No way of getting user IP when behind a load balancer

It seems that timezone is always saved as "America/New_York".
This seems to be some sort of default / localhost value.

I now have to do another check after login to see if NULL or "America/New_York" and update accordingly.

All of my calls to geoip()->getLocation() seem to work correctly, so don't know what's happening in in this library's Login listener that fails.

[Feature] - Ability to choose which flash message to use

Give the ability to choose what flash message we want to use to display the messages.

Why: Make it possible to turn off the flash message or use other flash message package such as mercuryseries/flashy, spatie/laravel-flash, mckenziearts/laravel-notify, etc.

Solution: On the configuration file we already have the flash attribute to define which package we want to use. Use that to turn off all flash messages 'flash' => 'off', and also a way to integrate other packages 'flash' => 'mercuryseries', 'flash' => 'spatie', 'flash' => 'mckenziearts', etc.

Cheers!

The library does not take the first found IP from 'lookup' config key

At this moment, the library takes the last found IP from the 'lookup' config key. In documentation there is written "Having in mind when the key is found inside the attribute, that key will be used.", and I believe it should be the first taken.

I'd go with this changes to the lookup() method:

private function lookup($type, $keys)
    {
        $value = null;

        foreach ($keys as $key) {
            if (request()->$type->has($key)) {
                return request()->$type->get($key);
            }
        }

        return $value;
    }

Complications when server uses proxies

I'm using this package successfully on my own server. However when trying to install it on a secondary server using proxies, it fails. It seems to rely on the REMOTE_ADDR header for the IP however my ITs are informing me that the real client IP is stored in a different header because of the proxy.

Is it possible to make the IP source configurable instead of pointing to REMOTE_ADDR only ?

[Feature] - Have the ability to define the default date format.

Hey @jamesmills,

I would like to be able to define the default date formate using the configuration file.

Why: When using the directive @displayDate, 99% of my cases I will have to define the format.

Solution: Use the configuration file to define the most used format and only define the directives the exceptions.

Feel free to question.

Cheers.

Improve performance. Avoiding extra request.

Hi,
I think you are making an extra request if you do not have to update the user timezone.
See L50-L60

Maybe you should check first if you have to update the user timezone. See recommended code below:

if (config('timezone.overwrite') == true || $user->timezone == null) {
        $ip = $this->getFromLookup();
        $geoip_info = geoip()->getLocation($ip);

        if ($user->timezone != $geoip_info['timezone']) {
                $user->timezone = $geoip_info['timezone'];
                $user->save();

                $this->notify($geoip_info);
        }
}       

localization

i use
App::setLocale($language);
Carbon::setLocale($language);
but with your package it not helps

Timezone will be saved automatically? or have to saved manually?

As described in the package description, I have published the vendor and it has added the timezone field to my users table migration file. I have migrated and it has added this field to table
but when I registered or login user it is not automatically updated timezone of the user in the database.

here is my code

$time = Timezone::convertToLocal($user->created_at);

Please do needful

Custom data source instead of users.timezone

In my apps, we do not store the timezone in users.timezone. We have a separate database table that stores various account-level settings, the timezone being only one of them. I suspect that others have similar implementations, or at the very least, a different column even.

With that, I'd like to make a suggestion. instead of mandating that we use users.timezone as the source of the user's timezone, allow for a model to return this information that can be customizable. Perhaps look in the User Eloquent model for a method with a specific naming convention (e.g. getUserTimezone())?

I am happy to contribute when I can - if you agree with my thinking.

use in model

i want to use this command in my model like this:

    public function getTimeAttribute($value){
        return Timezone::convertFromLocal($this->start);
    }

but it returns this error:
Class 'App\Timezone' not found

'time_zone' instead of 'timezone'

Hello!
Using your package I've encountered such bug: geoip()->getLocation($ip) returns an array with key time_zone, but in login event listener i found timezone key usage. Is this key depends on GeoIP service? I`m using IPGeolocation.

Environment:
PHP: 7.4.12
Laravel: 8
jamesmills/laravel-timezone: 1.9.3
torann/geoip: dev-master (downloaded today, 07.04.2021)

Maybe there is a problem in dependency, and i should rely on certain stable versions of torann/geoip? Latest stable version 3.0.2 differs from dev-master only in environment files like composer.json, so timezone key should have been changed earlier, i think.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.