PHP date_default_timezone_set() from GMT offset is possible?
im mySQL db I have:
|timezoneid | gmt_offset | dst_offset | timezone_code | zone_name
| 1 | -12 | 0 | NULL | (GMT-12:00) International Date Line West
I want to be able to set time zones from database
Check the output of DateTimeZone::listAbbreviations(), it gives you a full list of supported timezones and corresponding offsets. You should check the exact output yourself, since you get nested arrays.
Also note that not all timezones have an exact full hour offset to UTC, some regions add 30 or 45 minutes too.
Related
I have an eloquent model where i got two columns 'startdate' and 'enddate'. I wanna display all the models that are ongoing in the current week, i.e. any date between 'startdate' and 'enddate' that matches any date of the current week.
I first tried to get by only using the startdate like this:
$startOfWeek = Carbon::now()->startOfWeek()->startOfDay();
$endOfWeek = Carbon::now()->endOfWeek()->endOfDay();
$modelThisWeek = Model::whereBetween('startdate', [$startOfWeek, $endOfWeek])->get();
But naturally, anything that started more than a week ago, but is still ongoing ('enddate' is not finished yet) won't show up.
How could i get all the models valid for the current week efficiently?
Edit: So what I kinda want to do (sounds stupid now) is to get all the dates in between 'startdate' and 'enddate' like in an array for example, get a second array of all dates in between the current week and use like an array_intersect and get those models. I hope I explained that a bit more clearly this time.
Edit 2: Some sample data and expected result.
Data in DB:
--------------------------------------------------
| ID | some_other_col | startdate | enddate |
--------------------------------------------------
| 1 | ... | 12. Jan 17 | 20. Feb 17 |
--------------------------------------------------
| 2 | ... | 12. Jan 17 | 18. Jan 17 |
--------------------------------------------------
| 3 | ... | 30. Jan 17 | 04. Feb 17 |
--------------------------------------------------
| 4 | ... | 04. Feb 17 | 07. Feb 17 |
--------------------------------------------------
| 5 | ... | 08. Feb 17 | 10. Feb 17 |
--------------------------------------------------
So if I want all the models within the current week:
29. Jan 17 - 05. Feb 17
I expect the models with the ID 1, 3, 4;
Like all the models that are ongoing within the two dates (startOfWeek and endOfWeek).
Your problem is quite simple if you define 2 possible outputs
Your model got starting and ending dates
Your model got only starting date (ending date is null)
First output you already covered, so only second output need to cover up
Your query should look like for both outputs
$modelThisWeek = Model::where(['startdate','>='$startOfWeek],
['enddate','<=', $endOfWeek])
->orWhere(function ($query) {
$query->where('enddate', '>', $endOfWeek);
})
})->get();
It will maybe need some tweaks (I didn't totally understand you if you check for this week and you want in output still ongoing model which may started few weeks ago etc). Try it and if there is any more additional condition feel free to ask.
Looks like I am having a case of Monday morning!!!
Setup
As you can my local machine is in Eastern time zone with Day light Saving is in effect. That can be seen from 'date' command below.
date ; php -r 'echo mktime() .PHP_EOL ;'
Mon Apr 18 11:14:29 EDT 2016
1460992469
I then generated a unix timestamp using php. It is suppose to give your current time and convert that to Unix epoch at UTC 0:0:0 on Jan 1 1970.
My mysql Session is set to UTC, which I imagine 1460992469 represent as it is converted to UTC by mktime.
The Problem
The trouble is the conversion back to est does not recognizes Daylight Saving. Can anyone help to point the flaw in my logic.
SELECT CONVERT_TZ(FROM_UNIXTIME(1460992469), ##session.time_zone ,'EST') as converted_to_est , FROM_UNIXTIME(1460992469) , ##session.time_zone;
+---------------------+---------------------------+---------------------+
| converted_to_est | FROM_UNIXTIME(1460992469) | ##session.time_zone |
+---------------------+---------------------------+---------------------+
| 2016-04-18 10:14:29 | 2016-04-18 15:14:29 | UTC |
+---------------------+---------------------------+---------------------+
I tried using 'EDT' in CONVERT_TZ to no avail already .
Don't use 'EST'. Use 'America/New_York' (assuming United States).
I have found myself in need of replacing certain returned results from a MySQL Select Query. I have the following table and data (simplified for example purposes)
uid | duration | range | unique | stamp
-----------------------------------------------------------------
23 | d | 43 | 1 | 1
24 | d | 65 | 0 | 2
25 | d | 76 | 0 | 3
26 | d | 33 | 0 | 4
27 | d | 44 | 1 | 5
28 | d | 43 | 1 | 6
29 | d | 67 | 0 | 7
30 | d | 88 | 0 | 8
31 | d | 63 | 0 | 9
The stamp column is what I want to do the replace on. Rather than a simple text replace, I was wondering if its possible to run some sort of user defined function on the column and replace it dynamically.
For example If the data returned in the stamp column is a 1, I would like it to replace it with today's timestamp, if it is a 2 then yesterdays timestamp, a 3, the day before yesterdays and so on and so forth.
So my question is, is it possible to point REPLACE to a function that processes the value and then returns what to replace it with. Or if not, is there another way to accomplish this.
I could obviously post process the returned data in PHP and make the changes, but with millions of records returned, it will increase the load time considerably.
EDIT TO MAKE THINGS A BIT CLEARER: I want to replace the stamp column in the data returned from a SELECT Query, I am not storing the data anywhere, or replacing the data in the table. The table will remain unchanged.
Thanks
Absolutely possible:
UPDATE stamps
SET stamp = CURRENT_DATE - INTERVAL stamp - 1 DAY;
Fiddle here. Note that you have to decrement the stamp value by 1 to "minus 0 days" for a stamp of 1. If you remove the - 1, you'll end up storing yesterday's date for stamp values of 1.
UPDATE to answer your question about doing it on SELECT:
SELECT CURRENT_DATE - INTERVAL stamp - 1 DAY
FROM stamps;
Updated Fiddle here
You can use the case statement of mysql
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
If you are just trying to retrieve the results, use the following:
SELECT CURDATE() - INTERVAL stamp -1 DAY FROM myTable
How should I store my "dates + times" in a PostgreSQL database?
This is what I want to achieve:
How can I have all the entries that occurred on (for example) 1 January 2012 00:00:00 local time anywhere in the world?
Display all the entries sorted by date according to UTC time. (2012 New Year Eve in New York is more recent than the New Year in London).
How should I store my data? I have read that PostgreSQL stores all time in UTC internally (PostgreSQL documentation), so my users timezone is in fact lost.
I think I should use one column with type "timestamp without timezone":
Point 1 is easy.
And with another column of type "String" I will store the timezone string (e.g : America/New_York)
but then, point 2 seems still hard to do ....
I hope I am clear.
Edit new idea: I think with storing two timestamps: one without timezone (1. ok) and one with timezone (2. ok)
Yes, PostgreSQL stores all timestamps as UTC internally. For a timestamp with time zone the time zone offset is only applied to adjust the time to UTC, but is not stored explicitly.
I would not store the timezone string or even less a time zone abbreviation (those are not precise). This can later require expensive computation, because you have to consider daylight savings time and other oddities of the international time regime.
You can either store the time zone offset as interval (takes 12 bytes) or a numerical amount of seconds (takes 4 bytes as integer) like I demonstrate in this related answer.
Or, like you already proposed: store the local timestamp in addition to the UTC timestamp (takes 8 bytes). That would make your tasks easy. Consider the following demo::
-- DROP TABLE tbl;
CREATE TEMP TABLE tbl (id int, ts_tz timestamp with time zone, ts timestamp);
INSERT INTO tbl VALUES
(1,'2012-1-1 00:00+01','2012-1-1 00:00+01')
,(2,'2012-1-1 00:00+02','2012-1-1 00:00+02')
,(3,'2012-1-1 00:01+03','2012-1-1 00:01+03')
,(4,'2012-1-1 00:02+04','2012-1-1 00:02+04');
Query for question 1:
SELECT *
FROM tbl
WHERE ts = '2012-1-1 00:00'::timestamp;
id | ts_tz | ts
----+------------------------+---------------------
1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
Query for question 2:
SELECT *
FROM tbl
ORDER BY ts_tz;
id | ts_tz | ts
----+------------------------+---------------------
4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00
3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00
2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
The tricky part with this solution may be to enter the local timestamp. That's easy as long as all data is entered locally. But it needs consideration if you enter data for, say, New York in Los Angeles. Use the AT TIME ZONE construct for that:
SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp
, ('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp
timezone | timezone
---------------------+---------------------
2011-12-31 19:00:00 | 2011-12-31 16:00:00
Note how I use a timestamp with time zone as input. AT TIME ZONE gives different results for timestamps with or without time zone.
I guess you could store the date as a string and use ISO 8601 or RFC 2822 so you also store the timezone.
Or indeed for more comparison options store timestamp and timezone in 2 different columns.
I have a php script which gives server time, but as per knowledge, we can get the user's machine time and time zone with the help of client side scripts (javascript). I have mysql table which has dates stored along with timezone from where it was stored with the help of form. I need to show the data on a web page along with the time stored in the table, but it should be per user's machine.
rowid | date | timezone | data |
----------------------------------
12 | 2010-07-13 12:30:00 | Asia/Kolkata | This is data field |
143 | 2010-07-13 12:30:00 | Europe/Prague | This is data field |
Now, when I show date on web page, I need to show the above date per user's machine timezone.
A workaround logic would be that, if I could pass the date (2010-07-13 12:30:00) to some JS method which will take two time zone as input and convert the given date into user's machine's timezone. Or Something else?
Please help?
See the following link:
http://us3.php.net/manual/en/function.date-timezone-set.php
You can set the timezone in the script before displaying the dates although make sure you insert all the times in the DB as GMT.