2015-01-19 3 views
0

Я хочу рассчитать дату на основе метки времени и некоторых других сведений.Почему дата дает мне неправильную дату?

Моя функция выглядит следующим образом:

function getLastDeliveryDate($timestamp,$endOfMonth=true,$extraMonth=0){ 

    $days    = 0; 
    $extraDays   = 0; 
    $endOfCurrentMonth = 0; 
    $tsDay    = 86400; 

    if($endOfMonth){ 
     $endOfCurrentMonth = date("t", $timestamp) - date("d",$timestamp); 
     //rest of days in current month. In this sample 16 days 
    } 

    for($i=0;$i<$extraMonth;$i++){ 
     $x = $i + 1; 
     $date = new DateTime(date("Y-m-d", $timestamp)); //create dateobject to add a month 
     $date->modify("+{$x} month"); // add the month (next month) 
     $extraDays += date("t", strtotime($date->format("Y-m-d"))); 
     // get the days of the selected month and add them to count 
     // in this case its 31 + 30 + 31 = 92 
    } 

    $days = $endOfCurrentMonth + $extraDays; 
    // count everything together 16 + 92 = 108 days 

    return date("d.m.y", $timestamp + ($tsDay*$days)); 
    //returning date with 108 days added. 
} 

В качестве образца я вызываю функцию, как:

// the timestamp is 2015-07-15 
echo getLastDeliveryDate(1436911200, true, 3); 
// should return 2015-10-31 

Но это возвращение 2015-10-30 и я не знаю, почему. Но 108 дней - 2015-10-31. Что здесь происходит?

Если я называю

echo getLastDeliveryDate(1436911200, true, 2); 

его правильно и дает мне 2015-09-30

На самом деле я всегда сразу хочу, в последний день месяца.

EDIT:

Wired, если я проверить это здесь: IDEONE все работает отлично. Im мой проект не :(

+0

Проверить смещение временной зоны? – Mouser

+0

Даже если у меня это уже в прошедшей метке? Угадайте, что это не потому, что базовая дата правильная ... и возвращенные дневные счета также правы. Так что этого не может быть .. дней все 24 часа даже в timbugtu: D – Dwza

+0

вы действительно устанавливаете '$ endOfMonth' вручную? для чего это? существует механический и «простой» способ проверить, находится ли метка времени в последний день месяца ... – ITroubs

ответ

1

Вам нужно создать объект типа DateTime перед циклом:.

$date = new DateTime(date("Y-m-d", $timestamp)); //create dateobject to add month 
// simpler alternative: $date = new DateTime("@$timestamp"); 
for($i=0;$i<$extraMonth;$i++){ 
    $date->modify("+1 month"); // add the month (next month) 
    // $extraDays += date("t", strtotime($date->format("Y-m-d"))); 
    // you can reduce this line to: 
    $extraDays += $date->format("t"); 
} 

// Result: 15-10-31 

иначе всегда 31 добавил, потому что вы используете день временной метки + 1 месяц

Примечание:

Вы можете уменьшить всю функцию к этому:

function getLastDeliveryDate($timestamp,$endOfMonth=true,$extraMonth=0){ 
    $date = new DateTime("@$timestamp"); 
    $date->modify("+$extraMonth month"); 
    if ($endOfMonth) 
     $date->modify("last day of this month"); 
    return $date->format("d.m.y"); 
} 
+0

Нет, это неправильно. Он хочет создать его в цикле, чтобы получить дни выбранного месяца с данной отметки времени. Вот почему у меня есть x x там ... НО, вы правы, я мог бы удалить $ x и вызвать его извне ... на самом деле это просто лучший код :), но, плохо дайте ему попробовать, мама ... – Dwza

+0

нет, такой же результат – Dwza

+0

hmm ...возможно, я все еще прав ... я думаю, у меня есть другая проблема ... если я проверю это где-то еще ... у меня есть правильные результаты :(Anyways thx. Ill проголосовать за это и принять его, потому что это действительно лучший код для это то, что я/пытаюсь сделать :) – Dwza

1

Проблема - это переход на летнее время. Вы теряете один час 25 октября 2015 года. Поскольку ваша метка времени равна 0:00:00, вы теряете один час, в результате чего «30.10.2015 23:00:00» должно быть действительно 0:00:00

function getLastDeliveryDate($timestamp,$endOfMonth=true,$extraMonth=0){ 

    $days = 0; 
    $extraDays = 0; 
    $endOfCurrentMonth = 0; 
    $tag = 86400; 
    if(date('H',$timestamp)==0){$timestamp+=3601;} 
    if($endOfMonth){ 
    $endOfCurrentMonth = date("t", $timestamp) - date("d",$timestamp); 
    } 

    $date = new DateTime(date("Y-m-d", $timestamp)); 
    for($i=0;$i<$extraMonth;$i++){ 
     $date->modify("+1 month"); 
     $extraDays += $date->format("t"); 
    } 

    $days = $endOfCurrentMonth + $extraDays; 
    return date("d.m.y", $timestamp + ($tag*$days)); 

} 

echo getLastDeliveryDate(1436911200, true, 3); 

Этот код имеет грязное исправление для этой проблемы, добавив один час и одну секунду, если ваше время datetime установлено на 0:00:00. Когда вы не заботитесь о самих часах, это решение решит вашу проблему и будет в любом случае жизнеспособным. Если вы заботитесь о часах, вы должны проверить, находитесь ли вы в летнее время или нет, и действуйте соответствующим образом.

+0

Это очень грязное исправление: D Я все еще даю вам +1, потому что ответен как правильно :) Я не возражаю против часов. Но да, к тому времени, когда я понял, что настало время. Но решение Джеральда было приятным, и мой источник тоже загорелся :) – Dwza

+0

Вы правы. Его решение лучше. Дневной свет Экономия времени может испортить вещи действительно хорошо .... – ITroubs

Смежные вопросы