9

我有一个有点奇怪的问题。是否可以在 PHP 中为脚本工作的时间设置假日期?我正在使用使用时间段的 API,例如当您发送请求以获取一些数据时,您可以指定时间段(例如一个月,但这些时间段是固定的),它将从 request_time-1month 返回结果到 request_time。显然,请求数据是当前时间,所以我想模拟这个当前时间(例如设置从 5 月 10 日到 4 月 15 日的日期)。可能吗?我在 PHP 文档中看不到任何有用的东西,我什至不知道它是否会起作用,因为我不确定这个 API 是使用它工作的服务器还是存储上述数据的独立服务器的时间。但也许有人有任何想法。

预先感谢。

4

5 回答 5

15

使用 libfaketime ( https://github.com/wolfcw/libfaketime )。在 ubuntu 上 - 只需使用 apt-get 或 aptitude 安装 faketime。

  1. 如果您想为控制台应用程序伪造时间:

    LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 FAKETIME="2008-01-01 00:00:00" php yourscript.php
    
  2. 如果你想伪造 apache 时间,你需要在启动 apache 时预先加载 libfaketime。就放

    export FAKETIME="2008-01-01 00:00:00"
    export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1
    

进入 /etc/apache2/envvars 并重新启动 apache。现在您的服务器响应将始终看起来像

$ curl -D - http://localhost
HTTP/1.1 200 OK
Date: Tue, 01 Jan 2008 00:00:00 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Tue, 01 Jan 2008 00:00:00 GMT
ETag: W/"420419-b1-4429c2a6653ac"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html

2019 年更新:

在最新的系统上,您需要 64 位版本的 libfaketime,因此您需要 LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1(感谢@jtrautmann),甚至是 libfaketimeMT。 so.1 在多线程环境中。

此外,还有三种方法可以指定伪造的时间:

  • 通过设置环境变量 FAKETIME
  • 通过使用环境变量 FAKETIME_TIMESTAMP_FILE 中给出的文件
  • 通过使用主目录中的文件 .faketimerc
  • 通过使用文件 /etc/faketimerc 作为系统范围的默认值

此外,在 docker 容器中使用 libfaketime 是完全有效的。

于 2014-08-06T21:03:12.510 回答
2

如果您要连接的 API 使用“request_time - 1 个月”,那么您的脚本认为时间无关紧要,只有API 背后的脚本认为它是什么时间。(打个愚蠢的比喻:如果一家商店在下午 5 点关门,提早放表不会让您在 5:30 进店;您需要潜入并更改墙上的时钟,以免工作人员锁定向上。)

因此,除非您能找到一种方法让远程 API 误以为您在不同时间发送了请求,否则您无能为力。

如果您控制 API,则只需编辑 API 以具有覆盖“现在”定义的参数,可能仅在特殊调试模式下允许。

于 2013-05-10T11:49:00.583 回答
1

实际上,您通过 PHP 访问的日期和时间就是服务器的系统时间。因此,如果您能够改变这一点,您就可以实现您所需要的。看看这个答案:https ://stackoverflow.com/a/3923946/977431

虽然就个人而言,我建议只使用从当前日期返回 -30 天(例如)的函数。当您想更改日期时,请将函数替换为 real getdate()

于 2013-05-10T11:43:33.433 回答
0

你到底想做什么?如果您正在测试某些东西,则根本不应该依赖系统配置 - 最好执行以下操作:

my_function(\DateTime $now = null) {

  if($now === null) {
      return new \DateTime();
  } else {
      return $now;
  }

}

在您的正常代码中,您只需调用my_function(),但在您的测试中,您调用

$now = \DateTime::createFromFormat(...);
my_function($now);

如果它用于生产代码,则类似的想法。将日期作为参数传递,而不是离开函数来获取它。

my_function(\DateTime $datetime) {
  // does stuff
}
call_my_function() {
  my_function(new \DateTime());
}
other_way_to_call_my_function() {
  $datetime = \DateTime::createFromFormat(...);
  my_function($datetime);
}
于 2013-05-10T11:47:21.060 回答
0

这对我有用:

apt-get install faketime
faketime '2021-04-26 08:15:42' php cron.php
于 2021-01-30T01:27:24.290 回答