Timezone is correct but Time is not - PHP MySQL - php

I'm making a little twitter clone just for learning and I came across a problem where, before and after allowing users to select the timezone they are in, the time displaying when they would tweet a certain thing was wrong.
Here are snippets of my code:
/* current date/time whenever they send a tweet */
$time = date('Y-m-d H:i:s');
/* Insert into db as `time` */
/* Time retrieved as $value['time'] & users timezone as $_SESSION['timezone'] */
/* Convert to users timezone */
$users_timezone = new DateTimeZone($_SESSION['timezone']);
$date = new DateTime($value['time']);
$date->setTimeZone($users_timezone);
$new_date = $date->format('M j, o g:i a e');
echo $new_date;
It is currently 11:32am here in the LA area, yet after conversion it shows 6:26pm
My default is in Berlin, which it is currently 8:33pm but before conversion it shows 1am
Can anyone give me any insight into this? First time doing this.

Check System Time
Please check your current system time of your server by running date via ssh.
I believe php gets the date from the system therefore if your system time is incorrect then your php time would also be incorrect.
Check $value['time']
You are using the construct method within the DataTime class. Here is the documentation for that method.
http://www.php.net/manual/en/datetime.construct.php
Make sure $value['time'] is in an acceptable format. On way to do this easily is to use the strtotime function. This will make a unix timestamp from $value['time'] and that will probably satisfy the construct method of the DateTime class.

Related

Converting a date from local timezone to UTC

I have a Laravel-based app that is used by people from various parts of the US.
I am capturing a timestamp in Javascript when the user takes a specific action, and then I am submitting that timestamp as form data, for the Laravel/PHP to process.
The timestamp that I am capture in Javascript is in typical "YYYY-MM-DD HH:MM:SS" format.
I have the timezone the user is in stored in a database.
I basically want to take that timestamp, and convert it to UTC time, so that all timestamps in the database are UTC.
That is where I am struggling.
I have the following PHP code:
$defaultTime = request('submitted-time-stamp'); //In this case, we'll say 2022-12-21 12:01:01
$defaultTZ = $user->time_zone; //Translates to America/Denver
$utcTime = new DateTime($defaultTime);
$convertedTime = $utcTime1->setTimeZone(new DateTimeZone('UTC'));
$formattedTime = $convertedTime->format("Y-m-d H:i:s");
echo $formattedTime;
This code – it isn't producing any errors per sé... but it is showing the wrong time. It's showing the time that it went in as, not the time converted to UTC.
Basically, if I submit "2022-12-21 12:01:01" as the time, the converted time SHOULD be "2022-12-21 19:01:01", but it's still just echoing out "2022-12-21 12:01:01".
What am I missing here?
setTimezone() changes the timezone of the object from whatever default it was created with. I.e., it means, "convert from the existing timezone to this new timezone." It does not mean, "interpret the time as if it were in this timezone." If the original string didn't contain some sort of timezone identifier, then that default is whatever your PHP config says.
$when = new DateTime('2022-12-21 12:01:01');
echo $when->getTimeZone()->getName();
This will be the same as:
echo date_default_timezone_get();
Which is probably not what you want unless all your users are in the same timezone as your server.
In order to create a DateTime object in a specific known timezone that is not the same as your server's default, you'll need one of two things -- either a timezone representation in the input string:
$when = new DateTime('2022-12-21 12:01:01 America/New_York');
Or an explicit default timezone passed as a second parameter to the DateTime constructor:
$userDefaultTzStr = 'America/New_York'; // read this value from the database
$defaultTz = new DateTimeZone($userDefaultTzStr);
$when = new DateTime('2022-12-21 12:01:01', $defaultTz);
This latter method is (probably) preferred. If the input string contains any sort of timezone identifier, that will be used and the second parameter will be ignored. But if the input string does not contain any sort of timezone identifier, then the string will be interpreted as if it were in the indicated timezone.
Using Carbon it's very trivial.
use Carbon\Carbon;
$date = Carbon::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');
echo $date->format('Y-m-d H:i:s');
It should be the same thing with Laravel's Date facade.
use Illuminate\Support\Facades\Date;
$date = Date::create(request('submitted-time-stamp'), $user->time_zone);
$date->tz('UTC');
echo $date->format('Y-m-d H:i:s');

timestamp from both date & time inputs and compare php

I've been struggling to get an exact answer for this question. There are many that are close to what I'm wanting but seem to still be just off. The application of this is to ensure that a booking can't be made for a past date.
I have a form which has an input for time & another for date. Firstly, I wan't to take both of these inputs & convert them to a timestamp.
This code returns nothing
$time_date = sprintf("%s %s", $pDate, $pTime);
$objDate = DateTime::createFromFormat('H:ia d/m/Y', $time_date);
$stamp = $objDate->getTimestamp();
echo $stamp;
So I've have tried using something like this
$pDate = $_POST['pDate'];
$pTime = $_POST['pTime'];
$full_date = $pDate . ' ' . $pTime;
$timestamp = strtotime($full_date);
echo $timestamp;
But for some reason it is returning an incorrect timestamp. (i've been using an online converter) 02/06/2014 as date & 12:23am as time, is not 1401625380. This according to the converter is Sun, 01 Jun 2014 12:23:00 GMT.
Does someone have working code for returning a timestamp of both time & date inputs?
Secondly I want to compare this timestamp with a specified one & check to see if it is greater than. I've created a timestamp for my timezone with this
$date = new DateTime(null, new DateTimeZone('Pacific/Auckland'));
$cDate = $date->getTimestamp();
echo $cDate;
and will simply have an if statement which compares the two and echos the appropriate message.
I feel as though there are multiple question on here that are ALMOST what I'm wanting to achieve but I can't manage to get them working. Apologies for the near duplicate.
Note: I'm using ajax to post form data (if this could possibly interfere).
Your second code snipped is correct. Assuming it's in datetime format (Y-m-d H:i:s).
From php manual about strtotime():
Each parameter of this function uses the default time zone unless a time zone is specified in that parameter.
Check your PHP default time zone with date_default_timezone_get() function.
To compare two dates, be sure they both are in same time zones.
For datetime inputs I personally use jQuery UI timepicker addon.
you receiving the time and date in string format - so i don't believe the ajax can interfere.
as for your question:
first of all - find out what is the locale timezone of your server. you can do it by this function: date_default_timezone_get.
if the answer doesn't suit you - you can use its "sister": date_default_timezone_set, and change it to whatever value you need (like 'Pacific/Auckland' - see the documentation there). it is also recommended to return it to the original value after you finish your stuff.
i believe fixing your locale timezone will solve your issue.

Manage PHP time function

I am using godaddy hosting service and I can manage local time, I have to use the server default time that is America/Phoenix.
Even if i am using date_default_timezone_set("Asia/Kolkata");
function in my config file then also there is no difference in time and godaddy people are not ready to help me with, I am tired of calling this guys but no response, I hate them all.
Is there any means I can get my local time using any function or any external API?
I am using this code
//set time zone india
date_default_timezone_set("Asia/Kolkata");
$timezone = date_default_timezone_get();
echo "The current server timezone is: " . $timezone;
$date = date('m/d/Y h:i:s a', time());
echo $date."<br>";
and the output that I am getting is
The current server timezone is: Asia/Kolkata05/14/2014 12:06:26 am
Even if it is 4:38 pm here...
date_default_timezone_set should work for PHP functions like date, however I'm going to hazard a guess that you're having problems with date/time elements in a database such as MySQL.
I know I've had similar problems before, when trying to get everything on UTC instead of Europe/London...
When you've established the connection to your database, be sure to run this query:
SET time_zone = 'Asia/Kolkata';
This, in addition to date_default_timezone_set, should solve your problems. However, if you're using DATETIME columns, then those will not be fixed. TIMESTAMP columns will be automagically fixed to the new timezone because they are saved as UTC internally and converted upon retrieval.
You shouldn't touch date_default_timezone_set. The proper way to do that would be to use DateTimeZone object. Something like this:
$now = new \DateTime('now', new \DateTimeZone('Asia/Kolkata'));
echo $now->format(\DateTime::ATOM);
So, the idea is that you create an object in a timezone of server and then convert it to your timezone

PHP & MySQL: Converting Stored TIMESTAMP into User's Local Timezone

So I have a site with a comments feature where the timestamp of the comment is stored in a MySQL database. From what I understand, the timestamp is converted to UTC when stored, then converted back to the default timezone when retrieved. In my case, my server is in the Central Daylight Time timezone (CDT).
I have a plan to get the timezone from each user via entry form. I just wanted to know how to convert the TIMESTAMP value into the user's timezone.
First, would I convert from UTC to local timezone? Or CDT to local timezone?
Secondly, how would I go about doing that in PHP? Would I just do:
$userTimezone = new DateTimeZone($userSubmittedTimezoneString);
$myDateTime = new DateTime($storedTimestamp, $userTimezone);
...or is that not correct?
Date/time/datetime values are stored in MySQL as you supply them. I.e. if you INSERT the string 2012-04-17 12:03:23 into a DATETIME column, that's the value that will be stored. It will be converted internally into a timestamp which may or may not be accurate (see below), but when you query for the value again, you'll get the same value back out; the roundtrip is transparent.
Problems may occur if you try to do time calculations inside SQL. I.e. any operation that requires SQL to take the timezone and/or the server time into account. For example, using NOW(). For any of those operations, the timezone and/or server time should be set correctly. See Time Zone Problems.
If that doesn't concern you and you only need to do calculations in PHP, you only need to make sure you know from which timezone to which timezone you want to convert. For that purpose it can be convenient to standardize all times to UTC, but it is not necessary, as timezone conversions from any timezone to any other timezone work just as well, as long as you're clear about which timezone you're converting from and to.
date_default_timezone_set('Asia/Tokyo'); // your reference timezone here
$date = date('Y-m-d H:i:s');
/* INSERT $date INTO database */;
$date = /* SELECT date FROM database */;
$usersTimezone = new DateTimeZone('America/Vancouver');
$l10nDate = new DateTime($date);
$l10nDate->setTimeZone($usersTimezone);
echo $l10nDate->format('Y-m-d H:i:s');
There is no reliable way to get the user's timezone. Timezone information is not sent in HTTP headers. The best that you could do is either:
Match the IP address againsta geographic database
-or-
Use Javascript to get the time set on the user's computer and either send that to the server (AJAX) or make the time string on the client.
$timezone = new DateTimeZone('America/Vancouver');
$date = new DateTime(date('m/d/Y h:i:s a', time()));
$date->setTimeZone($timezone);
echo $date->format('l F j Y g:i:s A')."\n";
Replace new DateTime(date('m/d/Y h:i:s a', time())); with new DateTime("UTC Time");
You can create a new DateTimeZone() object for each user input.
The way to do it is by using javascript. I think the best way to do it is by storing the users GMT into his cookies, and retrieving it on the PHP process form.
<script language="javascript">
function TimeZoneCookie()
{
var u_gmt = (-(new Date().getTimezoneOffset()))/60;
var o_date = new Date("December 31, 2025");
var v_cookie_date = o_date.toGMTString();
var str_cookie = "utimezone="+u_gmt;
str_cookie += ";expires=" + v_cookie_date;
document.cookie=str_cookie;
}
//---------------------
TimeZoneCookie();
</script>
u_gmt explained:
Date().getTimezoneOffset() returns the offset to GMT-0 in minutes
Since getTimezoneOffset() will return the offset to GMT-0 and not from GMT-0 we'll need to turn it around. How? simple, just by knowing that -*-=+ & -*+=-. If you know basic math, you already know this principle.
As I said in step 1 getTimezoneOffset() will return the offset in minutes, so we just divide it by 60, so we can get the gmt offset format.
Result: (-(new Date().getTimezoneOffset()))/60
Now retrieve the cookie in PHP:
<?php
$user_timezone = $_COOKIE['utimezone'];
?>

Showing timezone specific dates in views with Zend_Date

I'm storing all my dates in ISO-format, so all of them look like this:
2010-08-17T12:47:59+00:00
Now, when my application starts, I register the timezone the current user resides in. In my case, this would be "Europe/Berlin":
date_default_timezone_set("Europe/Berlin");
However, when Zend_Date parses ISO dates, it overrides the default timezone set earlier and now has the UTC timezone.
But when I output this date in my view scripts I want it to show the date in the correct timezone.
Are there better solutions than writing a custom view helper just for this? (If this was the correct solution, shouldn't there already be a "DateViewHelper"?)
Not sure how this works with Zend_Date but given the fact that you use PHP >= 5.2 you can use the built-in DateTime class (which offers less functionality but is extremely faster):
$date = new DateTime('2010-08-17T12:47:59+00:00');
$date->setTimezone(new DateTimeZone(date_default_timezone_get()));
echo $date->format(DateTime::W3C);
EDIT
Just checked Zend_Date and it actually works the same here...
$date = new Zend_Date('2010-08-17T12:47:59+00:00', Zend_Date::ISO_8601);
$date->setTimezone(date_default_timezone_get());
echo $date->getIso();

Categories