donglingyi4679 2013-08-28 00:34
浏览 73
已采纳

DateTime“上个月的第一天”没有返回第一天

I looked at this answer already, and it's quite close to what I have.

Here is my PHP code:

$start = new DateTime('0:00 first day of previous month', new DateTimeZone('UTC'));
/*
if (isset($_GET['year']) && isset($_GET['month']) && checkdate($_GET['month'], 1, $_GET['year'])) {
    $start = DateTime::createFromFormat('Y-m-d', $_GET['year'] . '-' . $_GET['month'] . '-1');
}*/
$middle = DateTime::createFromFormat('U', strtotime('first day of last month', $start->format('U')));
$middle->setTimezone(new DateTimeZone('UTC'));
$end = DateTime::createFromFormat('U', strtotime('first day of 2 months ago', $start->format('U')));
$end->setTimezone(new DateTimeZone('UTC'));

var_dump($start);
var_dump($middle);
var_dump($end);

Today is August 27th, so I would expect July 1, June 1, and May 1. Here's what the actual output is:

object(DateTime)[1]
  public 'date' => string '2013-07-01 00:00:00' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

object(DateTime)[2]
  public 'date' => string '2013-05-02 00:00:00' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

object(DateTime)[3]
  public 'date' => string '2013-04-02 00:00:00' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

Why is it returning the second day of the months for me?

I've also tried it without the new DateTimeZone('GMT') as the second parameter of the constructor for the initial DateTime but it still gives me the same result, just with different times.

  • 写回答

2条回答 默认 最新

  • doujianwei8217 2013-08-28 00:40
    关注

    this part irrelevant - question was edited

    Because of the timezone difference. $start is calculated in the 'Rainy River timezone', while $middle and $end are in UTC time. The 'Rainy River timezone has a -06:00 hour offset from UTC (exactly the difference in hours between the first with the second and third results).

    update 1 - solution

    It seems the problem lies somewhere around strtotime. For some reason it yields a result with an offset of one day (further explanation needed). A simple solution, is to subtract one second from that date and it will produce the correct result.

    $timezone = new DateTimeZone('UTC');
    $start = new DateTime('0:00 first day of previous month', $timezone );
    $middle = DateTime::createFromFormat('U', strtotime('first day of last month',($start  ->format('U'))-1),$timezone);
    echo $middle->format('Y-m-d')."
    ";
    

    Result:

    2013-05-01
    

    update 2 - reason for problem

    Eventually I find out that the problem originates from the instantiation of the fisrt date object. Here is an illustration.

    This will give a correct result:

    $original = new DateTime('2013-05-01');
    echo $original->format('Y-m-d')."
    ";
    
    $previous= DateTime::createFromFormat('U', strtotime('first day of last month',($original->format('U'))),new DateTimeZone('UTC'));
    echo $previous->format('Y-m-d')."
    ";
    

    Result (OK):

    2013-05-01
    2013-04-01   <--- OK
    

    However, this will not (only first line different, as in the original code):

    $original = new DateTime('0:00 first day of previous month', new DateTimeZone('UTC'));
    echo $original->format('Y-m-d')."
    ";
    
    $previous= DateTime::createFromFormat('U', strtotime('first day of last month',($original->format('U'))),new DateTimeZone('UTC'));
    echo $previous->format('Y-m-d')."
    ";
    

    Result:

     2013-07-01
     2013-05-02  <--- BAD
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 想问一下树莓派接上显示屏后出现如图所示画面,是什么问题导致的
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号