|
- <?php
- /*
- 64位时间戳计时转换公式PHP7算法 带时区星期毫秒。
- 本程序为64位PHP7.3.1环境编写,低于该版本可能会出现语法解析错误,不支持32位PHP。
- 本算法计算0年1月1日0时0分0秒与指定日期所经历的毫秒数,存在bug楼下回复。
- */
- define('OYM',[31,28,31,30,31,30,31,31,30,31,30,31]); //平年月份表
- define('LYM',[31,29,31,30,31,30,31,31,30,31,30,31]); //闰年月份表
- define('OYW',[6,2,2,5,0,3,5,1,4,6,2,4]); //平年月代码(计算星期用)
- define('LYW',[5,1,2,5,0,3,5,1,4,6,2,4]); //闰年月代码
- define('ODD',[0,31,59,90,120,151,181,212,243,273,304,334]); //平年某月1日与1月1日距离天数
- define('LDD',[0,31,60,91,121,152,182,213,244,274,305,335]); //闰年某月1日与1月1日距离天数
- define('UNIX_TIMESTAMP64',62167190400000); //1970年1月1日的64位时间戳(用于与Unix时间戳转换)
- define('TEXT_WEEK_CN',['星期日','星期一','星期二','星期三','星期四','星期五','星期六']);
- function his_to_sec($hour,$minute,$second){ //时分秒求1天中的多少秒 返回0~86399
- return $hour * 3600 + $minute * 60 + $second;
- }
- function sec_to_his($sec,&$hour,&$minute,&$second){ //1天中的多少秒0~86399 求时分秒
- $hour = floor($sec / 3600) %24;
- $minute = floor($sec / 60) %60;
- $second = $sec %60;
- }
- function is_leap_year($year){ //是否为闰年
- return ($year %4 == 0 && $year %100 !=0 || $year % 400 == 0) ? 1 : 0;
- }
- function get_total_leap_year($year){ //计算指定年数有多少个闰年
- return floor($year/4) - floor($year/100) + floor($year/400);
- }
- function get_year_total_day($year){ //计算指定年数有多少天(带闰年)
- return $year * 365 + get_total_leap_year($year);
- }
- function get_1year_day($year){ //取指定1年有多少天(平年返回365闰年366)
- return is_leap_year($year) ? 366 : 365;
- }
- /*
- 已知月日获取1年中的第几天(平年最大返回365闰年最大366最小1)
- 参数1:月 参数2:日 参数3:平年0闰年1 (失败返回0)
- */
- function month_day_arrive_day($month,$day,$leap){
- if(!is_ymdhis(!$leap,$month,$day)){
- return 0;
- }
- return ($leap ? LDD[$month-1] : ODD[$month-1]) + $day;
- }
- /*
- 已知1年中的第几天获取几月几日
- 参数1:天数(平年最大返回365闰年最大366)
- 参数2、3:月、日(变量传出)
- 参数3:平年0闰年1 成功返回1失败返回0(失败不会改变变量)
- */
- function day_arrive_month_day($days,&$month,&$day,$leap){
- if($days < 1 || $days > ($leap ? 366 : 365)) {
- return 0;
- }
- for($dec=12;$dec>0;$dec--){
- $month_code = $leap ? LDD[$dec-1] : ODD[$dec-1];
- if($days > $month_code){
- $month = $dec;
- $day = $days - $month_code;
- break;
- }
- }
- return 1;
- }
- function get_year_first_week($year){ //获取指定年份1月1日是星期几 星期1为1 星期2为2 ... 星期日为0
- return ((1+get_year_total_day($year)-get_1year_day($year))%7);
- }
- function get_year_month_have_day($year,$month){ //已知年月求该月有多少天(失败返回0)
- if($year < 0 || $month < 1 || $month > 12) {
- return 0;
- }
- return is_leap_year($year) ? LYM[$month-1] : OYM[$month-1];
- }
- function is_ymdhis($year=0,$month,$day,$hour=0,$minute=0,$second=0,$millisecond=0){ //年月日是否有效
- if($year < 0 || $month < 1 || $day < 1 || $hour < 0 || $minute < 0 || $second < 0 || $millisecond < 0){
- return 0;
- } elseif($hour > 23 || $minute > 59 || $second > 59 || $millisecond > 999 || $month > 12){
- return 0;
- }
- return ($day <= get_year_month_have_day($year,$month)) ? 1 : 0;
- }
- function get_week($year,$month,$day){ //年月日取星期几 星期日为1 星期1为2 (失败返回0)
- if(!is_ymdhis($year,$month,$day)) {
- return 0;
- }
- $leap = is_leap_year($year);
- $first_week = get_year_first_week($year);
- $year_code = $leap ? (($first_week+2)%7) : (($first_week+8)%7);
- $month_code = $leap ? LYW[$month-1] :OYW[$month-1];
- $week = ($year_code + $month_code + $day) % 7;
- if($week == 0) {
- $week = 7;
- }
- return $week;
-
- }
- function get_day_total_year($day){ //已知天数求出有多少年(含闰年)
- $sday = $day;
- $year400 = floor($sday / 146097);
- $sday %= 146097;
- $year100 = floor($sday / 36524);
- $sday %= 36524;
- $year4 = floor($sday / 1461);
- $sday %= 1461;
- if($sday <= 365){
- $year1=0;
- } elseif($sday <= 730){
- $year1=1;
- }elseif($sday <= 1095){
- $year1=2;
- } else {
- $year1=3;
- }
- return $year1 + $year4*4 + $year100 * 100 + $year400 * 400;
- }
- function ymd_to_day($year,$month,$day){ //已知年月日计算与0年1月1日距离多少天
- $leap = is_leap_year($year);
- return month_day_arrive_day($month,$day,$leap) - $leap + get_year_total_day($year);
- }
- function day_to_ymd($days,&$year,&$month,&$day){ //计算0年1月1日的未来指定天数等于指定年月日(成功返回1失败0)
- $year = get_day_total_year($days);
- if($year % 100 == 0){
- $year = get_day_total_year($days -1);
- }
- $leap = is_leap_year($year);
- $days -= get_year_total_day($year);
- return day_arrive_month_day($days + $leap,$month,$day,$leap);
- }
- /*
- 64位时间戳编码 成功返回时间戳 失败或溢出返回 -1
- 参数1~7:年 月 日 时 分 秒 毫秒
- 参数8:时区(小数,默认为8)
- */
- function timestamp64_encode($year,$month,$day,$hour=0,$minute=0,$second=0,$millisecond=0,$time_zone=8){
- if(!is_ymdhis($year,$month,$day,$hour,$minute,$second,$millisecond)){
- return -1;
- }
- $return = his_to_sec($hour,$minute,$second) * 1000 + $millisecond;
- $return = ymd_to_day($year,$month,$day) * 86400000 - $time_zone * 3600000 + $return;
- if($return < 0) {
- return -1;
- }
- return $return;
- }
- /*
- 64位时间戳解码 成功返回1,计算失败或溢出返回0 (如果返回0不要对传出的变量进行任何操作)
- 参数1:64位时间戳
- 参数2~9(必须为变量):年、月、日,星期、时、分、秒、毫秒。
- 参数10:时区(小数,默认为8)
- 其中星期日为1,星期一为2 (年、月、日为必须参数变量其余允许留空)
- */
- function timestamp64_decode($timestamp64,&$year,&$month,&$day,&$week =0,&$hour=0,&$minute=0,&$second=0,&$millisecond=0,$time_zone=8){
- $timestamp64 = $timestamp64 + $time_zone * 3600000;
- if($timestamp64 < 0){
- return 0;
- }
- $millisecond = $timestamp64 % 1000;
- $timestamp64 = floor($timestamp64 / 1000);
-
- sec_to_his($timestamp64 % 86400,$hour,$minute,$second);
- $timestamp64 = floor($timestamp64 / 86400);
- day_to_ymd($timestamp64,$year,$month,$day);
- if(!is_ymdhis($year,$month,$day,$hour,$minute,$second,$millisecond)){
- return 0;
- }
- $week = get_week($year,$month,$day);
- return 1;
- }
- function timestamp64_to_unix($timestamp64){ //64位时间戳转Unix时间戳(不保留毫秒)
- return floor($timestamp64/1000) - UNIX_TIMESTAMP64/1000;
- }
- function unix_to_timestamp64($unix){ //Unix时间戳转64位时间戳
- return $unix * 1000 + UNIX_TIMESTAMP64;
- }
- function test(){ //以下函数用于测试,正式调用请删除
- $ms = microtime(1);
- $ms = floor(($ms - floor($ms))*1000);
- $timestamp64 = timestamp64_encode(date("Y"),date("m"),date("d"),date("H"),date("i"),date("s"),$ms);
- $unix1 = time();
- echo "64位时间戳:".$timestamp64."<br>";
- $unix2 = timestamp64_to_unix($timestamp64);
- echo "转换后Unix时间戳:".$unix2."<br>";
- echo "time函数取出Unix时间戳:".$unix1."<br>";
- timestamp64_decode($timestamp64,$y,$m,$d,$w,$h,$i,$s,$ms);
- $w = TEXT_WEEK_CN[$w-1];
- echo " {$y}年{$m}月{$d}日 {$w} {$h}时 {$i}分 {$s}秒 {$ms}毫秒";
- }
- test();
- ?>
复制代码 |
|