PHP时间处理总结


php 时间函数

获取0-3个月的时间戳
$now = time();
strtotime("+0 year +3 month +0 day");

strtotime("-0 year -1 month -0 day");
php获取三个月前的时间戳:

strtotime("-0 year -3 month -0 day");
php获取六个月前的时间戳:

strtotime("-0 year -6 month -0 day");
php获取一年前的时间戳:

strtotime("-1 year -0 month -0 day");

关于时区时区会影响所有内置的时间函数 如:strtotime()

function_exists('date_default_timezone_set');  //在这他总是返回1,这函数是判断这里面的字符是不是一个定义了的函数名 
date_default_timezone_set("Etc/GMT");      //这是格林威治标准时间,得到的时间和默认时区是一样的 
date_default_timezone_set("Etc/GMT+8");    //这里比林威治标准时间慢8小时 
date_default_timezone_set("Etc/GMT-8");    //这里比林威治标准时间快8小时 
date_default_timezone_set('PRC');          //设置中国时区 

常用函数

mktime(hour,minute,second,month,day,year,is_dst)

参数 描述
hour 可选。规定小时。
minute 可选。规定分钟。
second 可选。规定秒。
month 可选。规定用数字表示的月。
day 可选。规定天。
year 可选。规定年。在某些系统上,合法值介于 1901 - 2038 之间。不过在 PHP 5 中已经不存在这个限制了。
is_dst 可选。如果时间在日光节约时间(DST)期间,则设置为1,否则设置为0,若未知,则设置为-1。自 5.1.0 起,is_dst 参数被废弃。因此应该使用新的时区处理特性。

根据时间显示刚刚,几分钟前,几小时前的实现代码

/**
 * 根据时间显示`刚刚`,`几分钟前`,`几小时前`
 * @param $time 时间戳
 * @return false|string
 * eq:
 * $date = "1351836000";
 * echo tranTime($date);
 */
function tranTime($time)
{
    date_default_timezone_set('PRC');//注意时区
    $rtime = date("m-d H:i", $time);
    $htime = date("H:i", $time);

    $time = time() - $time;

    if ($time < 60) {
        $str = '刚刚';
    } elseif ($time < 60 * 60) {
        $min = floor($time / 60);
        $str = $min . '分钟前';
    } elseif ($time < 60 * 60 * 24) {
        $h = floor($time / (60 * 60));
        $str = $h . '小时前 ' . $htime;
    } elseif ($time < 60 * 60 * 24 * 3) {
        $d = floor($time / (60 * 60 * 24));
        if ($d == 1)
            $str = '昨天 ' . $rtime;
        else
            $str = '前天 ' . $rtime;
    } else {
        $str = $rtime;
    }
    return $str;
}

时间本地化处理 今天 明天

/**
 * 时间本地化处理
 * @param $time
 * @return false|string
 * eq:
 * $date = "1351836000";
 * echo dealTimeShow($date);
 */
function dealTimeShow($time)
{
    date_default_timezone_set('PRC');//注意时区
    //当前时间区间
    $beginToday = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
    $endToday = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')) - 1;
    //明天时间区间
    $beginTomorrow = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y'));
    $endTomorrow = mktime(0, 0, 0, date('m'), date('d') + 2, date('Y')) - 1;

    if ($beginToday <= $time && $time <= $endToday) {
        return '今天';
    }

    if ($beginTomorrow <= $time && $time <= $endTomorrow) {
        return '明天';
    }

    if ($time > $endTomorrow) {
        return date('Y/m/d', $time);
    }
}

今日昨日上周本月的起始时间戳和结束时间戳的方法

date_default_timezone_set('PRC');
//php获取今日开始时间戳和结束时间戳
$beginToday = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
$endToday = mktime(0, 0, 0, date('m'), date('d') + 1, date('Y')) - 1;
//php获取昨日起始时间戳和结束时间戳
$beginYesterday = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y'));
$endYesterday = mktime(0, 0, 0, date('m'), date('d'), date('Y')) - 1;
//php获取上周起始时间戳和结束时间戳
$beginLastweek = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1 - 7, date('Y'));
$endLastweek = mktime(23, 59, 59, date('m'), date('d') - date('w') + 7 - 7, date('Y'));
//php获取本月起始时间戳和结束时间戳
$beginThismonth = mktime(0, 0, 0, date('m'), 1, date('Y'));
$endThismonth = mktime(23, 59, 59, date('m'), date('t'), date('Y'));

取得时间范围内的月份日期组合 并返回数组

$time1 = strtotime('2014-02-04'); // 自动为00:00:00 时分秒 两个时间之间的年和月份  
$time2 = strtotime('2015-02-06');

$monarr = array();
$monarr[] = '2014-02'; // 当前月;  
while (($time1 = strtotime('+1 month', $time1)) <= $time2) {
    $monarr[] = date('Y-m', $time1); // 取得递增月;   
}

print_r($monarr);

返回当前时间与给定时间间的天数

//今天与2008年9月9日相差多少天  
$Date_1 = date("Y-m-d");
$Date_2 = "2008-10-11";
$d1 = strtotime($Date_1);
$d2 = strtotime($Date_2);
$Days = round(($d2-$d1)/3600/24);
echo "今天与2008年10月11日相差" . $Days . "天";

获取两个日期相隔的天数 天
使用场景:2017/6/28 0:0:0 和2017/6/27 23:59:59这样的日期差别是1天

/**
 * 获取两个日期相隔的天数 天
 * @param $date1 当前时间
 * @param $date2 应还款时间
 * @return string 比较出来的时间是带正负(+-)符号的
 */
function getTimeToTimeDaysByTime($date1, $date2)
{
    $datetime1 = date_create(date('Ymd', $date1));
    $datetime2 = date_create(date('Ymd', $date2));
    $interval = date_diff($datetime1, $datetime2);
    $overdue_days = $interval->format('%R%a');
    return $overdue_days;
}

eq:

$time = time();
/**
 * 注意事项:时间的比较会带(+-)符号,当然如果$interval->format('%a')这样的话就不带符号了,但是比较不出哪个时间早哪个时间晚
 * 比较规则是:data_diff($day2,$day1);后面的数减去前面的数,如果后面的数比前面的大就为正数,否则为负数
 */
#date_create的比较适合这种场景,相差1秒钟就差了一天
$day1 = date_create(date('Ymd', strtotime('2017/6/28 0:0:0')));
$day2 = date_create(date('Ymd', strtotime('2017/6/27 23:59:59')));
$diff = date_diff($day2, $day1);
$diff_days = $diff->format("%R%a");
echo $diff_days;
echo "
"; $datetime1 = date_create(date('Ymd', $time));//当前时间 $datetime2 = date_create(date('Ymd', $time - 86400 * 20));//应还款时间 $interval = date_diff($datetime2, $datetime1); $overdue_days = $interval->format('%R%a');//已经还款但是逾期的天数 echo $overdue_days;//比较出来的时间是带正负(+-)符号的 if ($overdue_days > 0) { echo '$datetime1比$datetime2大:' . intval($overdue_days) . '天' . PHP_EOL; } else { echo '$datetime1比$datetime2小:' . intval($overdue_days) . '天' . PHP_EOL; } $overdue_days = ($overdue_days > 0) ? intval($overdue_days) : $overdue_days; echo $overdue_days; echo "
"; $day1 = date_create("20170628"); $day2 = date_create("20170601"); $diff = date_diff($day2, $day1); $diff_days = $diff->format("%R%a"); echo $diff_days;

返回两个时间内的所有日期

// 两个日期之间的所有日期  
function prDates($start, $end)
{
    $dt_start = strtotime($start);
    $dt_end = strtotime($end);
    while ($dt_start <= $dt_end) {
        echo date('Y-m-d', $dt_start) . "\n";
        $dt_start = strtotime('+1 day', $dt_start);
    }
}

prDates('2005-02-01', '2005-02-05');

返回两个时间内相差的月的数量

/**
 * @author injection(injection.mail@gmail.com)
 * @var date1 日期1
 * @var date2 日期2
 * @var tags 年月日之间的分隔符标记,默认为'-'
 * @return 相差的月份数量
 * @example:
 * $date1 = "2003-08-11";
 * $date2 = "2008-11-06";
 * $monthNum = getMonthNum( $date1 , $date2 );
 * echo $monthNum;
 */
function getMonthNum($date1, $date2, $tags = '-')
{
    $date1 = explode($tags, $date1);
    $date2 = explode($tags, $date2);
    return abs($date1[0] - $date2[0]) * 12 + abs($date1[1] - $date2[1]);
}

echo getMonthNum('2015-12-5', '2018-6-8');

PHP计算两个时间段是否有交集(边界重叠不算)

/**
 * PHP计算两个时间段是否有交集(边界重叠不算)
 *
 * @param string $beginTime1 开始时间1
 * @param string $endTime1 结束时间1
 * @param string $beginTime2 开始时间2
 * @param string $endTime2 结束时间2
 * @return bool
 */
function is_time_cross($beginTime1 = '', $endTime1 = '', $beginTime2 = '', $endTime2 = '')
{
    $status = $beginTime2 - $beginTime1;
    if ($status > 0) {
        $status2 = $beginTime2 - $endTime1;
        if ($status2 >= 0) {
            return false;
        } else {
            return true;
        }
    } else {
        $status2 = $endTime2 - $beginTime1;
        if ($status2 > 0) {
            return true;
        } else {
            return false;
        }
    }
}

mysql查询两个时间段是否有交集

1.需求:查询两个时间段是否有交集
2.分析:分为三种情况:
入参:查询开始时间,查询结束时间
数据库字段:start_date,end_date
    2.1 :查询开始时间在start_date与end_date之间,则肯定有交集
    2.2 :查询结束时间在start_date与end_date之间,则肯定有交集
    2.3:查询开始时间>=start_date,查询结束时间<=end_date,则肯定有交集
其余情况则无时间范围的交集了。

3.sql成型:
3.1:正常思路的sql例子
按照上述思路,sql如下:
select * from 某个table c 
where 
((c.start_date >= '2018-01-01' and c.start_date<= '2018-12-31')
OR (c.end_Date >= '2018-01-01' and c.end_Date<= '2018-12-31')
OR (c.start_date <= '2018-01-01' and c.end_Date>= '2018-12-31'))
AND c.`status`=3;
3.2:反向查询的sql思路:
只要start_date>查询结束时间,则本条数据与当前查询时间范围肯定无交集
只要end_date<查询开始时间,则本条数据与当前查询时间范围肯定无交集
所以,将上述两种结果合并,并且取反,则是时间范围有交集的数据。
sql如下:
select * from 某个table c
where c.`contract_type`=1
and not (c.`start_date`>'2018-12-31' or c.`end_date`<'2018-01-01')
and c.`status`=3

4.总结
上述两个sql结果条数是一致的。有时候,反向考虑问题,能得到更简洁的解决问题的方式

php处理大于2038年以后日期的一种方法 时间精度

/**
 * 获取日期
 * @param $timestamp
 * @return string
 * eq:
 * getDateTime('2444486400');
 */
function getDateTime($timestamp)
{
    $d = new DateTime('@' . $timestamp);
    $d->setTimezone(new DateTimeZone('PRC'));
    return $d->format('Y-m-d H:i:s');  //2047-06-19 00:00:00
}

/**
 * 获取时间戳
 * @param $time
 * @return string
 * eq:
 * getTimeStamp('2047-06-19 00:00:00');
 */
function getTimeStamp($time)
{
    $d = new DateTime($time);
    return $d->format('U'); //2444486400
}