changed laravel app timezone, time got from db did not change - laravel

Assume having a Eloquent model called Request with the column next_check autocasted as date (protected $dates = ['next_check'];).
APP_TIMEZONE is initial Europe/Helsinki (+02:00)
$ artisan tinker
Psy Shell v0.10.4 (PHP 7.4.11 — cli) by Justin Hileman
>>> $pr = Request::find(1);
>>> $pr->next_check = Carbon\Carbon::now();
>>> $pr->save();
>>> Request::find(1)->next_check;
=> Illuminate\Support\Carbon #1603973824 {#2900
date: 2020-10-29 14:17:04.0 Europe/Helsinki (+02:00),
}
That looks all fine and we saved 14:17:04 assuming we're in Helsinki.
Now changing the timezone to Europe/Berlin (+01:00), I would assume to get 13:17:04 returned.
>>> Request::find(1)->next_check;
=> Illuminate\Support\Carbon #1603977424 {#2900
date: 2020-10-29 14:17:04.0 Europe/Berlin (+01:00),
}
The timezone is changed but still there is the time returned, which was originally saved in Europe/Helsinki time.
Is that an expected behaviour and how can I get my desired behaviour that a change of the app timezone would result in converted times?
p.s.: the db timezone configured in laravel is still the default '+00:00'

If you want to localise times so they show to user in the user's timezone, you need to CONVERT an existing datetime:
$users_timezone = 'Europe/Berlin';
$datetime->setTimezone($users_timezone);
This will actually change the time according to the difference between the app's timezone and the one converted to.

To get my expected behaviour, I now found a solution. If anybody else want's that exact same behaviour, this might be the solution:
Add the following call in your AppServiceProvider's boot-method:
$this->setUTCOffsetInDBConnection();
The setUTCOffsetInDBConnection method's code is as following:
// according to https://www.sitepoint.com/synchronize-php-mysql-timezone-configuration/
private function setUTCOffsetInDBConnection() {
$now = new \DateTime();
$mins = $now->getOffset() / 60;
$sgn = ($mins < 0 ? -1 : 1);
$mins = abs($mins);
$hrs = floor($mins / 60);
$mins -= $hrs * 60;
$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);
DB::statement("SET time_zone='".$offset."';");
}
This will always synchronize the timezone according to your app's timezone and save the timestamps as UTC in the database.
When you now save a timestamp 2020-10-29 15:28:00 from your app with APP_TIMEZONE=Europe/Berlin in your .env, it will save it as UTC in the database (2020-10-29 15:28:00).
When you change your APP_TIMEZONE to Europe/Helsinki now, you will get 2020-10-29 16:28:00 returned.
Be aware that your phpMyAdmin might still not show the saved UTC times in your database since also phpMyAdmin sets the servers timezone when opening the connection. So if your server which runs phpMyAdmin is also in Europe/Berlin, you will see 2020-10-29 15:28:00 and not the UTC date saved in the DB.

Answer to "Is that an expected behaviour" is YES
To "save" the timezone with the date data, you have to save it too as an extra column.
So having both "2020-10-29 14:17:04.0" and "Europe/Helsinki" in DB will allow you to remember what timezone was used to save this date, so if it's changed, you can convert.
But first you should consider not to change your app and DB timezone, both should remain UTC.
See https://medium.com/#kylekatarnls/always-use-utc-dates-and-times-8a8200ca3164
So so you can easily convert them into any timezone and display it properly according to the user timezone while keeping a standard well-known format in DB.

Related

What is the Zone Id for GMT in Java 8

I want to get the difference in seconds to find whether the system timezone is ahead or behind the remote timezone. Here the remote timezone value is "GMT" which i fetch from Database. It could be "US/Eastern", which i convert to "America/New_York". But for GMT, im getting ERROR.
ZoneId.systemDefault().getRules().getOffset(Instant.now()).getTotalSeconds()
- ZoneId.of("GMT").getRules().getOffset(Instant.now()).getTotalSeconds()
But it gives the following error,
Exception in thread "main" java.time.DateTimeException: Invalid ID for ZoneOffset, invalid format:
at java.time.ZoneOffset.of(Unknown Source)
at java.time.ZoneId.of(Unknown Source)
at java.time.ZoneId.of(Unknown Source)
How to resolve this error ?
What to use in place of GMT ??
Use Etc/UTC
import java.time.Instant;
import java.time.ZoneId;
public class Main {
public static void main(String args[]) {
System.out.println(ZoneId.of("Etc/UTC").getRules().getOffset(Instant.now()).getTotalSeconds());
}
}
Output:
0
The official answer is:
Etc/GMT
It’s the same as the Etc/UTC suggested in the other answers except for the name.
For the sake of completeness there are a number of aliases for the same, many of them deprecated, not all. You can find them in the link.
And I am not disagreeing with the comments telling you to prefer UTC. I just wanted to answer the question as asked.
For your case you should not need to ask at all though. ZoneId.of("GMT").getRules().getOffset(Instant.now()).getTotalSeconds() should always yield 0, so there is no need to subtract anything. I would either insert a comment why I don’t or subtract a well-named constant with the value 0.
Link: List of tz database time zones
It's ZoneId.of("UTC")...
Here's evidence:
public static void main(String[] args) {
// define the ZoneId
ZoneId utc = ZoneId.of("UTC");
// get the current date and time using that zone
ZonedDateTime utcNow = ZonedDateTime.now(utc);
// define a formatter that uses O for GMT in the output
DateTimeFormatter gmtStyleFormatter = DateTimeFormatter
.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS O");
// and print the datetime using the default DateTimeFormatter and the one defined above
System.out.println(utcNow + " == " + utcNow.format(gmtStyleFormatter));
}
output (some moments ago):
2020-09-16T08:02:34.717Z[UTC] == 2020-09-16T08:02:34.717 GMT
Getting the total zone offset in seconds of this zone by
utc.getRules().getOffset(Instant.now()).getTotalSeconds();
will result in 0, because this zone has no offset.

How to set Local Timezone when saving time into DB in Magneto

I have applied following things to make Default time zone to my local timezone i.e. 'Asia/Calcutta' --
1) changed in config.xml -
<general>
<locale>
<code>en_US</code>
<timezone>Asia/Calcutta</timezone>
</locale>
</general>
2) Changed in Mage.php -
if (is_readable($localConfigFile)) {
$localConfig = simplexml_load_file($localConfigFile);
date_default_timezone_set('Asia/Calcutta');
if (($date = $localConfig->global->install->date) && strtotime($date)) {
self::$_isInstalled = true;
}
}
Now when I am trying to insert any time in db using this code
Mage::getModel('core/date')->date('Y-m-d H:i:s');,
it does not work according to current timezone and saves 5:30 hours ahead date in DB. can anyone tell me how can I do it or Have I done something wrong in default timezone settings.

php - i am getting logged out after being idle

I do not want the user to be logged out of the site even if the person is idle for, it is okay if the person is logged out if he has closed the browser.
session.gc_maxlifetime = 180000
session.gc_probability = 1
session.gc_divisor = 1
session.save_path = "/var/lib/php/session"
cookie_lifetime = 0
Is there any setting that i am missing?
Please help
To set the life time i have added the following code.
session_set_cookie_params(21600);
session_start();
You need extend your live time of cookie, remember that session id is stored in user webbrowser within cookie, set session.cookie_lifetime with a more big value too.
session_set_cookie_params(21600);
session_start();
21600 seconds is only 6 hours
Try setting to something bigger maybe even PHP_INT_MAX
Dont know whether it will help just wrote to give u the idea of how?....cookie are saved at user browser so ,
$cookieName = "userscookie";
$lifetime = time() + (60*60*24); // one day life
if(isset($_COOKIE[$cookieName])) {
$value = $_COOKIE[$cookieName];
// one day life from day of access
setcookie($cookieName, $value, $lifetime);
} else {
$value = "this value to store";
setcookie($cookieName, $value, $lifetime);
}
output:
Thankyou

how to check that user is inactive for some specific duration?

I want to log out the user if he is inactive for some specific duration. USing sess_expiration in config file, it gives the timing from login not from inactive state.
So how can I do this using codeigniter?
you can store the time in a session when the user logging in like this:
$_SESSION['loginTime'] = time();
and when the user do any action in the system, check if the user exceed the specified time
if($_SESSION['loginTime'] < time()+$yourtime){
logout();
}else{
$_SESSION['loginTime'] = time();
}

Sinatra/Ruby time zone troubles between development & production

My Sinatra app is creating a simple object and persisting it to Postgres:
post '/' do
event = Event.new(params)
event.created_at = Time.now.utc
event.date = next_date(params[:dayofweek], params[:time]) if params[:dayofweek] && params[:time]
if event.save
status 201
event.to_json
else
json_status 400, event.errors.to_hash
end
def next_date(dayofweek, hour)
...
# some calculations that effectively culminate in the final line below
...
my_time = Time.utc(2012, 11, 9, 12, 0, 0) ## => 2012-11-09 12:00:00 UTC
end
Object saves successfully. But when I retrieve the object from my development environment I get (json):
{ ..., "date":"2012-11-23T20:00:00-08:00" } #notice the PST offset of -08:00.
I'm expecting the UTC time zone or +00:00. For some reason my development workstation, which is in PST, is factoring in its own time zone when saving to Postgres...at least that what it appears to be doing?!?
Sending the same code to the production server (Heroku) stores same data with proper offset of +00:00
How can I make my development workstation act like the production one? Or, how should I be creating a proper UTC Date object in Sinatra?
First verify that your data does a round-trip successfully:
event.created_at = Time.now.utc
event.date = ...whatever...
tmp_created_at = event.created_at
tmp_date = event.date
event.save
event.reload!
tmp_created_at == event.created_at or raise "created_at failed"
tmp_date == event.date_at or raise "date failed"
Second, verify that the JSON is accurate.
compare the JSON time string to the expected time
the JSON time string has the -08:00
is the JSON string the same actual time?
For example, if you expect 10:00Z, does the JSON show 02:00-08:00 (i.e. the same actual time) or 10:00-08:00 (not the same actual time-- this is eight hours later).
If the data round-trip works, and the JSON is the same actual time, then look at whatever JSON library you're using to print the strings. Look for a method like "iso8601" that will print the time in standard UTC format.
Also, it may be helpful to know that Postgres saves timestamps without the time zone by default.
"The SQL standard requires that writing just timestamp be equivalent to timestamp without time zone, and PostgreSQL honors that behavior. (Releases prior to 7.3 treated it as timestamp with time zone.) timestamptz is accepted as an abbreviation for timestamp with time zone; this is a PostgreSQL extension."
You can see this by describing the table, which may look something like this:
# \d events
Table "public.events"
Column | Type | Modifiers
-----------+-----------------------------+-----------------------------------
id | integer | not null default
name | character varying(255) |
created_at | timestamp without time zone | not null
updated_at | timestamp without time zone | not null
date | timestamp with time zone | not null
More info based on OP's feedback...
OP says: I'm using DataMapper and after digging around on their site I found "time properties will always be stored and retrieved in the timezone the datastore is set to" and a link to a gem that'll force a specific zone.
Because the round-trip shows a problem, try using a current version of the connection library e.g. a current DataMapper, and also try a current version of any similar library e.g. ActiveRecord (version 3.2.8 at the time of this writing).

Resources