Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Shift a giving months from your input datetime with month based

Shift a giving months from your input datetime with month based

If the target month is smaller than the original month, the extra days will be discarded.

/**
 * Shift a giving months from your input datetime with month based
 * 
 * If the target month is smaller than the original month, the extra days will be discarded.
 * 
 * @author  Nick Tsai <myintaer@gmail.com>
 * @example
 *  shiftMonths("2018-01-15", '+', 1);  // 2018-02-15
 *  shiftMonths("2018-01-31", '+', 1);  // 2018-02-28
 *  shiftMonths("2020-02-29", "-", 12); // 2019-02-28
 *  shiftMonths("2018-01-15", '+', 1, false);                   // 1518681600
 *  shiftMonths("2020-02-29 10:11:12", "-", 24, "Y-m-d H:i:s"); // 2018-02-28 10:11:12
 *
 * @param string Datetime string
 * @param string Operation: +/-
 * @param integer Number of months
 * @param string PHP date() format, empty returns Unix time
 * @return string|integer Date format|Unix time
 */
function shiftMonths($date, $operation='+', $months=1, $outputFormat="Y-m-d")
{
    $timestamp = strtotime($date);

    // Year
    $op = ($operation=='+') ? '+' : '-';
    $newBasetime = strtotime(date("Y-m-1 H:i:s", $timestamp) . " {$op}{$months} month");

    // Month
    $m = date("m", $newBasetime);

    // Day
    $lastDay = date("t", $newBasetime);
    $day = date("d", $timestamp);
    $day = ($lastDay <= $day) ? $lastDay : $day;
    $result = strtotime(date("Y-m-{$day} H:i:s", $newBasetime));

    return ($outputFormat) ? date($outputFormat, $result) : $result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment