PHP、Codeigniter:如何在 Web 应用程序中根据用户的时区/位置全局设置日期/时间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2274568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 05:50:00  来源:igfitidea点击:

PHP, Codeigniter: How to Set Date/Time based on users timezone/location globally in a web app?

phpdatetimecodeignitertimezone

提问by Abs

I have just realised if I add a particular record to my MySQL database - it will have a date/time of the server and not the particular user and where they are located which means my search function by date is useless! As they will not be able to search by when they have added it in their timezone rather when it was added in the servers timezone.

我刚刚意识到,如果我将特定记录添加到我的 MySQL 数据库中 - 它会有服务器的日期/时间,而不是特定用户及其所在的位置,这意味着我的按日期搜索功能没用!因为他们将无法在他们将它添加到他们的时区中而不是在服务器时区中添加它时进行搜索。

Is there a way in Codeigniter to globally set time and date specific to a users location (maybe using their IP) and every time I call date() or time() that users timezone is used.

Codeigniter 中是否有一种方法可以全局设置特定于用户位置的时间和日期(可能使用他们的 IP),并且每次我调用 date() 或 time() 时都使用用户时区。

What I am actually asking for is probably how to make my application dependent on each users timezone?

我实际要求的可能是如何使我的应用程序依赖于每个用户时区?

Maybe its better to store each users timezone in their profile and have a standard time (servers time) and then convert the time to for each user?

也许最好将每个用户的时区存储在他们的个人资料中并有一个标准时间(服务器时间),然后将时间转换为每个用户?

Thanks all

谢谢大家

采纳答案by Pekka

I think the easiest way is define a timezone for internal data storage (your server's time zone or UTC) and convert the time according to the user's time zone when outputting it.

我认为最简单的方法是为内部数据存储定义一个时区(您服务器的时区或UTC),并在输出时根据用户的时区转换时间。

I don't know CodeIgniter so I can't point you to the right functions. One prominent library that is timezone aware is Zend_Date: Working with TimezonesI have not worked with these functions yet but they look promising.

我不知道 CodeIgniter,所以我无法为您指出正确的功能。Zend_Date: Working with Timezones我还没有使用过这些函数,但它们看起来很有前途。

However, once you know the user's time zone, it's not difficult to put together an own function that adds/substracts the offset when outputting dates and/or times.

但是,一旦您知道用户的时区,就不难组合一个自己的函数,在输出日期和/或时间时添加/减去偏移量。

Possibly related question:

可能相关的问题:

回答by Shane

It sounds like what you need to do is store all of the date and times in your system as UTC time (used to be called GMT). This is the base time that everything in the world is calculated off of with adjustments. (eg: Central Time is -6 hours off of UTC)

听起来您需要做的是将系统中的所有日期和时间存储为 UTC 时间(以前称为 GMT)。这是世界上所有事物都经过调整计算得出的基准时间。(例如:中部时间与 UTC 相差 -6 小时)

In MySQL you can use UTC_TIMESTAMP() to get the current UTC time as long as your server and DB are configured with the correct times and timezone settings.

在 MySQL 中,只要您的服务器和数据库配置了正确的时间和时区设置,您就可以使用 UTC_TIMESTAMP() 来获取当前的 UTC 时间。

In PHP run this to set the timestamp of PHP to UTC (you will run this in your code so put it on every page or in a centralized index file):

在 PHP 中运行它以将 PHP 的时间戳设置为 UTC(您将在代码中运行它,因此将其放在每个页面或集中索引文件中):

date_default_timezone_set('UTC');

Or you can go directly into PHP.INI and tell it to use UTC time globally. (this may not work if you have multiple websites on a single installation of PHP.

或者您可以直接进入 PHP.INI 并告诉它全局使用 UTC 时间。(如果您在单个 PHP 安装上有多个网站,这可能不起作用。

And then anywhere in the system you need to get the current UTC time you can just call:

然后在系统中的任何地方,您需要获取当前的 UTC 时间,您只需调用:

time();

Then for each user in the system you will need to ask them what timezone they live in and then when you display times make the adjustment for that user. So if it is 5:00PM UTC and I live in Easter US (-5) the time would be 5:00 - 5 hours = 12:00PM.

然后对于系统中的每个用户,您需要询问他们居住在哪个时区,然后在显示时间时为该用户进行调整。因此,如果现在是 UTC 下午 5:00,而我住在美国复活节 (-5),则时间将是 5:00 - 5 小时 = 12:00 PM。

This can be a long process to get right but once you do your users will find it very useful especially internationally.

这可能是一个漫长的过程,但一旦你做到了,你的用户会发现它非常有用,尤其是在国际上。

回答by Donny Kurnia

Take an example of an existing web application such as WordPress and phpBB. Each user have their own timezone setting.

以现有的 Web 应用程序为例,例如 WordPress 和 phpBB。每个用户都有自己的时区设置。

When receiving a content from the user, use local_to_gmt()function in the Date Helperthen save the content into database using the gmt date. When fetching the data you will get the time in gmt. Get the user's timezone setting, then display the data in that timezone.

当接收到用户的内容时,使用Date Helperlocal_to_gmt()中的函数,然后使用 gmt 日期将内容保存到数据库中。获取数据时,您将获得以 gmt 表示的时间。获取用户的时区设置,然后显示该时区中的数据。

This way, you can save yourself from calculating between two timezone. Just make sure that your server's time is in correct setting, so all your data is in the correct gmt time.

这样,您可以避免在两个时区之间进行计算。只需确保您的服务器时间设置正确,以便您的所有数据都在正确的格林威治标准时间。

UPDATE:

更新:

Recently I review the last project I worked on that have timezone issue. After thinking various scenario, here is the solution for the timezone issue:

最近我回顾了我从事的最后一个有时区问题的项目。在考虑了各种情况后,这里是时区问题的解决方案:

  1. All data stored right now already using server's time. Changing this will takes times and prone to error, so I leave it like that.
  2. For the new data from user that set the content date to a certain date and time, I stored it into 2 column. First column is to store the data as is, and used to displaying it as is. Second column will be a recalculation of the date based on the user's timezone into server's timezone. This column is used in the WHEREstatement (filter based on server date) and for the ORDER(because this column's value all in same timezone, which is the server's timezone).
  1. 现在存储的所有数据已经​​使用服务器的时间。改变这需要时间并且容易出错,所以我就这样离开了。
  2. 对于来自用户的将内容日期设置为特定日期和时间的新数据,我将其存储到 2 列中。第一列是按原样存储数据,并用于按原样显示数据。第二列将根据用户的时区将日期重新计算为服务器的时区。此列用于 WHERE语句(基于服务器日期的过滤器)和用于ORDER(因为此列的值都在同一时区,即服务器的时区)。

This way, I only do 1 timezone calculation, which is to convert user date into server date. For displaying , I display the date according to server's datetime. Since all data stored in the same timezone, data can be ordered by the column that hold the server date value.

这样,我只做了1个时区计算,也就是将用户日期转换成服务器日期。为了显示,我根据服务器的日期时间显示日期。由于所有数据都存储在同一时区中,因此可以按保存服务器日期值的列对数据进行排序。

For the user that have set their timezone, the date from database can be easily recalculated to get the datetime in the user's timezone. Btw, in my application, I display the date using timeago jquery plugins. This plugins need time in the ISO8601format (UTC time). local_to_gmt()function in CodeIgniter can be used to do this.

对于设置了时区的用户,可以轻松地重新计算数据库中的日期以获取用户时区中的日期时间。顺便说一句,在我的应用程序中,我使用timeago jquery plugins显示日期。此插件需要ISO8601格式的时间(UTC 时间)。local_to_gmt()CodeIgniter 中的函数可用于执行此操作。

回答by ChazUK

Obviously the leap to British Summer Time (Daylight Savings Time) is a big confusion in the world of programming, and I am indeed caught up in that confusion.

显然,英国夏令时(夏令时)的飞跃是编程界的一大困惑,我确实陷入了这种困惑。

The best possible solution I can find (which I will try to coherently explain) when using a timezone sensitive system is this:

使用时区敏感系统时,我能找到的最佳解决方案(我将尝试连贯地解释)是这样的:

  • The Web Server and Database should both be running off the same machine timezone. I suggest UTC as it is the building blocks of timezone conversions. This will ensure that all of the dates stored in your database are constant, and don't skip any times such as the 1hour jump between Daylight Savings.
  • At the top of all of your PHP scripts use date_default_timezone_set('Europe/London');with the specific timezone of the user.
  • When producing dates from user submitted forms, use gmmktime();to ensure that the timestamp created is UTC and not altered by the timezone that you have set.
  • date();can be used when displaying dates, as this will convert the timestamp to the correct time taking into account the timezone that you have set.
  • If you do need to show a date in the UTC format then use gmdate();with the $gm_timestampthat you have taken from the database or created with gmmktime();.
  • Web 服务器和数据库都应该在相同的机器时区运行。我建议使用 UTC,因为它是时区转换的构建块。这将确保存储在数据库中的所有日期都是恒定的,并且不会跳过任何时间,例如夏令时之间的 1 小时跳跃。
  • 在所有 PHP 脚本的顶部使用date_default_timezone_set('Europe/London');用户的特定时区。
  • 从用户提交的表单生成日期时,用于gmmktime();确保创建的时间戳是 UTC 并且不会被您设置的时区更改。
  • date();可以在显示日期时使用,因为考虑到您设置的时区,这会将时间戳转换为正确的时间。
  • 如果你需要显示在UTC格式的日期,然后使用gmdate();$gm_timestamp您从数据库中取出或创建gmmktime();

I have written this bit of PHP to help understand the situation.

我写了这段 PHP 来帮助理解这种情况。

date_default_timezone_set('UTC');
$gmtime = gmmktime(2,0,0,03,29,2009);
$time = mktime(2,0,0,03,29,2009);
echo $gmtime.'<br />'.date('r',$gmtime).'<br />'.gmdate('r',$gmtime).'<br />';
echo $time.'<br />'.date('r',$time).'<br />'.gmdate('r',$time).'<br />';

date_default_timezone_set('Europe/London');
$gmtime = gmmktime(2,0,0,03,29,2009);
$time = mktime(2,0,0,03,29,2009);
echo $gmtime.'<br />'.date('r',$gmtime).'<br />'.gmdate('r',$gmtime).'<br />';
echo $time.'<br />'.date('r',$time).'<br />'.gmdate('r',$time).'<br />';

Hopefully I've done a good job, but I doubt it because I'm still trying to battle the problem in my head.

希望我做得很好,但我对此表示怀疑,因为我仍在努力解决头脑中的问题。

UPDATE:

更新:

Glad I did this, because I am now having doubts about the user inputted dates.

很高兴我这样做了,因为我现在怀疑用户输入的日期。

To get the User inputted date (taking into account their timezone) to match up with the UTC corresponding date in the database, you should put it through mktime(). And then use gmdate('U', $timestamp);to get the true UTC timestamp. (I think)

要让用户输入的日期(考虑到他们的时区)与数据库中的 UTC 对应日期相匹配,您应该通过mktime(). 然后用于gmdate('U', $timestamp);获取真正的 UTC 时间戳。(我认为)

Example

例子

Looking at it from a reporting side, the user is using the 'Europe/London' timezone. At the start of our PHP script we call date_default_timezone_set('Europe/London');, whilst the Database (and all the records within) is still in UTC.

从报告方面来看,用户使用的是“欧洲/伦敦”时区。在我们的 PHP 脚本开始时,我们调用date_default_timezone_set('Europe/London');,而数据库(以及其中的所有记录)仍使用 UTC。

The user then sends through that they want to select a list of books added to the database between 25/03/2010 10:00 to 30/03/2010 14:00. The PHP script then runs the date variables through mktime($hour, $minute, $second, $month, $day, $year)to generate a correct UTC timestamp. The start date will not change, but PHP knows that the end date is within the BST timezone, so changes the timestamp to UTC accordingly.

用户然后通过发送他们想要选择在 25/03/2010 10:00 到 30/03/2010 14:00 之间添加到数据库的书籍列表。PHP 脚本然后运行日期变量mktime($hour, $minute, $second, $month, $day, $year)以生成正确的 UTC 时间戳。开始日期不会改变,但 PHP 知道结束日期在 BST 时区内,因此相应地将时间戳更改为 UTC。

When the results are returned back to the user, date('r', $date_added)can be used to show the user the date the book was added to the database according to their set timezone.

当结果返回给用户时,date('r', $date_added)可用于根据用户设置的时区向用户显示图书添加到数据库的日期。

This link may help with understanding when it changes. http://www.daylightsavingtime.co.uk/

此链接可能有助于了解何时更改。http://www.daylight Savingtime.co.uk/

回答by Adam Kiss

I think recalculating to user's time is better option, since it gives you normalized time on server, i.e. if you'll need to look up something, that happened (from your point of view) hour ago, you won't have a mess with american, asian and e.g. australian time.

我认为重新计算用户的时间是更好的选择,因为它为您提供了服务器上的标准化时间,即,如果您需要查找某些事情,发生在(从您的角度来看)一小时前,您就不会搞砸了美国、亚洲和例如澳大利亚时间。

Just ask them for their timezone (usually select with major cities in that timezone) and then recalculate :)

只需询问他们的时区(通常选择该时区的主要城市)然后重新计算:)

Or, alternatively, you can store two timedates- one for your comparison and one to show, so you won't have so much calculations on serverside.

或者,您可以存储两个时间日期- 一个用于比较,一个用于显示,这样您就不会在服务器端进行太多计算。

Also, if recalculating, you can use date helper: http://ellislab.com/codeigniter/user-guide/helpers/date_helper.html

此外,如果重新计算,您可以使用日期助手:http: //ellislab.com/codeigniter/user-guide/helpers/date_helper.html

回答by spoulson

I've used the MySQL built-in timezone conversion. In the database, all datetimes are stored as UTC. In the select query, I used CONVERT_TZto convert to the user's timezone. You can specify timezone codes or hour invervals like:

我使用了 MySQL 内置的时区转换。在数据库中,所有日期时间都存储为 UTC。在选择查询中,我曾经CONVERT_TZ转换为用户的时区。您可以指定时区代码或小时 invervals,如:

SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');

But, the problem is this does not accommodate for daylight savings times. This is particularly frustrating since many parts of the world either don't honor daylight savings or honor it on different dates. So, if you install the timezone description tables, you can use descriptive names that will account for daylight savings automatically like:

但是,问题是这不适用于夏令时。这尤其令人沮丧,因为世界上的许多地方要么不遵守夏令时,要么在不同的日期遵守它。因此,如果您安装时区描述表,您可以使用自动考虑夏令时的描述性名称,例如:

SELECT CONVERT_TZ('2004-01-01 12:00:00', 'UTC', 'US/Eastern');

回答by AlunR

Codeigniter contains a helper which deals with all manner of date functions.

Codeigniter 包含一个处理各种日期函数的帮助程序。

Codeigniter Date helper

Codeigniter 日期助手

the command gmt_to_local() should help you... the third parameter is for 'daylight_saving'.

命令 gmt_to_local() 应该可以帮助您...第三个参数用于“daylight_saving”。

Takes a Unix timestamp (referenced to GMT) as input, and converts it to a localized timestamp based on the timezone and Daylight Saving time submitted. Example:
$timestamp = '1140153693';
$timezone = 'UM8';
$daylight_saving = TRUE;

echo gmt_to_local($timestamp, $timezone, $daylight_saving);

回答by Anjani Barnwal

Add this line to autoload.php in the application folder/config folder:

将此行添加到应用程序文件夹/配置文件夹中的 autoload.php 中:

$autoload['time_zone'] = date_default_timezone_set('Asia/Kolkata');