为什么timestamp unix time和time()之间的差异不正确?

时间:2016-03-24 08:41:48

标签: php mysql sql

我正在尝试在数据库中保存记录4小时后用cron执行php脚本。我的问题不在于cron,这里的一切都运行正常(我很确定这是因为我每隔4小时就收到来自守护进程cron的测试邮件)。

问题在于我计算时间戳,转换为unix和当前时间之间的差异,然后执行一些脚本。

但是这两次之间的区别是他们增加了3个小时,我不知道为什么但是我的脚本在7小时后执行,而不是4小时。有人可以帮帮我吗?

我的代码如下所示:

Activity A calls Activity B
Intent intent = new Intent(getApplicationContext(), HayvanKartiList.class);
                intent.putExtra("activityname",BuzagiKayitActivity.class);
                intent.putExtra("ciftlikoid", ciflikoid);
                startActivity(intent);

Activity B calls Activity A 
Intent i = new Intent(getApplicationContext(),  BuzagiKayitActivity.class);
            i.putExtra("kupeno", selItem.getKupeNo().toString());
            i.putExtra("hayvanoid", selItem.getOid().toString());
            startActivity(i);

数据库<?php require_once('some-path/wp-load.php'); global $wpdb; $constant= 4*3600; $table = 'notifications'; $data = $wpdb->get_results("SELECT * FROM $table WHERE status = 'pending'"); $time = time(); foreach ($data as $r){ $temp_data = strtotime($r->date_created); if ($time - $temp_data > $constant){ $email = $r->email; $message = 'test'; $subject = 'test'; $headers = 'From: test <test@test.com>' . "\r\n"; $headers .= 'Content-type: text/html; charset=utf-8' . "\r\n"; $mail_client = wp_mail($email, $subject, $message, $headers); if($mail_client){ $wpdb->update($tabel, array('status' => 'sent'), array('id_raport'=>$r->id_raport), array('%s'), array('%d')); } } }

的日期示例

现在,我知道我可以做这样的事情来获得真正的本地时间:

Using strtotime(): 1458814621, Directly from database "2016-03-24 10:17:01"

更新 但这会返回与time()方法相同的东西。

2 个答案:

答案 0 :(得分:5)

  

现在,我知道我可以做这样的事情来获得真正的本地时间:

date_default_timezone_set('Europe/Bucharest');
$date = date('m/d/Y h:i:s a', time());
$time = strtotime($date);

UNIX时间戳不是“本地”。 UNIX时间戳在全世界都是一样的。您在此代码中所做的只是将时间戳(time())转换为人类可读格式,然后将其重新解释为时间戳;结果与原始time()值相同(或者至少应该是!)。

人类可读的日期/时间格式,例如您从MySQL(2016-03-24 10:17:01)收到的 不完整 ,没有时区。世界上有超过24个不同的绝对时间点,它们是“2016-03-24 10:17:01”某处。那个时间戳本身并不是很有意义 当您使用strtotime将其转换为UNIX时间戳时,它必须接收其他信息以将这种模糊的相对时间格式转换为绝对时间点。该信息来自date_default_timezone_set,或者在您的php.ini中等效设置的任何内容。

你的问题几乎可以归结为PHP假设strtotime与你的MySQL日期时间字符串实际上不同的时区。例如,如果你的MySQL日期时间表示UTC的时间,但是strtotime假设布加勒斯特是使用的时区,那么你会看到在绝对时间点上差几个小时。

只需在PHP代码中设置/使用正确的时区即可;思考/了解/决定你的MySQL日期实际存储在哪个时区。

另见Does PHP time() return a GMT/UTC Timestamp?

答案 1 :(得分:1)

time()返回的值(时间戳)是自1970年1月1日00:00:00 UTC以来的秒数。这是一个绝对值。

您从数据库中检索的值(2016-03-24 10:17:01)是一个相对值。它可以表示不同的时间戳,具体取决于您使用的时区。

如何使用DateTimeDateTimeZone类:

 // Timestamp generated from PHP code
 // Current time
 $date1 = new DateTime();    // it uses the default timezone set in php.ini
                             // or by a previous call to date_default_timezone_set()
 // be more specific
 $date2 = new DateTime('now', new DateTimeZone('US/Eastern'));
 // $date1 and $date2 represent the same moment in time ("now")
 echo(($date1 == $date2) ? 'Yes' : 'No');    // It displays "Yes"
 // Display them as timestamps
 echo($date1->format('U'));      // 1458816551
 echo($date2->format('U'));      // also 1458816551
 // Display $date1 as human-readable format:
 echo($date1->format('Y-m-d H:i:s e'));
 // It displays: 2016-03-24 12:49:11 Europe/Bucharest
 // Change $date1 to use the same timezone as $date2
 $date1->setTimezone(new DateTimeZone('US/Eastern'));
 echo($date1->format('Y-m-d H:i:s e'));
 // Now it displays: 2016-03-24 06:49:11 US/Eastern

 // It provides easy ways to generate another date:
 $date3 = clone $date1;     // create a duplicate
 $date3->add(new DateInterval('P2D'));    // modify the duplicate
 // $date3 is 2 days in the future
 echo($date3->format('Y-m-d H:i:s e'));
 // It displays: 2016-03-26 06:49:11 US/Eastern

 // Get the difference between $date3 and $date1
 $diff = $date3->diff($date1)
 // you get the difference in date components (days, hours, minutes etc).
 print_r($diff);

从数据库中提取的日期时间值不完整。它缺乏时区。如果您以前将值存储在数据库中,那么您应该知道它使用的是什么时区。如果使用SELECT NOW()从数据库获取日期时间,则时区是服务器使用的默认时区。它存储在system_time_zone服务器变量中,可以使用SELECT @@system_time_zone

进行查询

查询:

SELECT NOW() AS now, @@system_time_zone AS tz

返回MySQL服务器使用的本地日期和时间以及时区。

您可以使用它们来创建要使用的DateTime对象,如上面提供的示例代码中所示。

作为一般规则,始终对数据库中存储为datetime的值使用一次。我建议使用UTC,因为一切都与它相关,并且它没有观察DST。或者您可以使用TIMESTAMP类型的列(绝对时间戳不关心时区和DST),但它们更难处理。