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 "<hr>";
$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 "<hr>";
$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
}