21,886
社区成员
发帖
与我相关
我的任务
分享
static function Date1970($zone){
return new DateTime('1970-01-01T00:00:00.0Z', $zone);
}
static function Date_MS($date){
$c=$date->diff(EDate::Date1970($date->getTimezone()));
$f=$c->invert?1:-1;
return ($c->days*24*60*60*1000+$c->h*60*60*1000+$c->i*60*1000+$c->s*1000+$f*round($date->format('u')/1000)-$f*8*60*60*1000)*$f;
}
static function MS_Date($ms){
$zone=new DateTimeZone('PRC');
if($ms<-2147483648000){
$ms-=343000;
}
$mi=intval(fmod($ms,1000));
if($mi<0){
$mi=1000+$mi;
$ms-=2*$mi;
}
$h=intval(abs($ms)/(60*60*1000));
$s=intval(fmod(abs($ms),60*60*1000)/1000);
$c=new DateInterval('PT'.$h.'H'.$s.'S');
$d=EDate::Date1970($zone);
if($ms>0){
$d->add($c);
}else{
$d->sub($c);
}
$d->setTimezone($zone);
$mi=substr('00000'.$mi*1000,-6);
$ds=$d->format('Y-m-d\TH:i:s').'.'.$mi.'Z';
$d=new DateTime($ds, $zone);
return $d;
}
echo MS_Date(-5364691199877);//1936-02-08 06:28:17.877
我电脑是IIS里面跑的PHP,IIS是32、64位模式都试过,PHP是64位的,1800的时间date方法好像处理不了,可能跨平台时间处理也是坑
PHP date方法介绍里面写的:
时间戳的有效取值范围为 GMT 时间的 1901 年 12 月 13 日至 GMT 时间的 2038 年 1 月 19 日。 (32 位有符号整数的取值范围)。 但是,在 PHP 5.1.0 之前的版本,在某些系统(例如 Windows)上有效取值范围为 1970 年 1 月 1 日至 2038 年 1 月 19 日。function MS_Date($n) {
if(is_numeric($n))
return date('Y-m-d H:i:s.', substr($n, 0, -3)) . substr($n, -3);
return substr((new DateTime($n))->format('Uu'), 0, -3);
}
$inp = 1451621405123;
echo $s = MS_Date($inp); //2016-01-01 12:10:05.123
echo MS_Date($s); //1451621405123
function MS_Date($n) {
if(is_numeric($n)) {
$r = date('Y-m-d H:i:s.', intval($n/1000));
$u = substr($n, -3);
return $r . $u;
}
$d = new DateTime($n);
return substr($d->format('Uu'), 0, -3);
}
1986年至1991年,每年四月的第2个星期日早上2点,到九月的第2个星期日早上2点之间。
1986年5月4日至9月14日(1986年因是实行夏令时的第一年,从5月4日开始到9月14日结束)
1987年4月12日至9月13日,
1988年4月10日至9月11日,
1989年4月16日至9月17日,
1990年4月15日至9月16日,
1991年4月14日至9月15日。
1986-1991,看样子是夏令时搞的鬼,DateTime没有问题,错怪它了,只怪自己不会用
JavaScript、asp、c#刚才测了一下,默认的都没考虑夏令时,他们之间的时间转换都能互通,php这样感觉是个坑
1936-02-08 06:28:16.123000
2016-10-10 12:00:00.123000
是我服务器哪里要配置一下还是?
new Date(-5364691199877).toLocaleString()//"1800/1/1 上午12:05:43"
第一个测试值,js算出来的和你算出来的有点出入
function udate($format, $timestamp=null) {
if (!isset($timestamp)) $timestamp = microtime();
if (count($t = explode(" ", $timestamp)) == 1) {
list($timestamp, $usec) = explode(".", $timestamp);
$usec = "." . $usec;
}else {
$usec = $t[0];
$timestamp = $t[1];
}
if($timestamp<0){
$usec = 1-$usec;
$timestamp = $timestamp-1;
}
$date = new DateTime(date('Y-m-d H:i:s' . substr(sprintf('%.7f', $usec), 1), $timestamp));
$result = $date->format($format);
return $result;
}
$utime = -5364691199.877000;
echo udate('Y-m-d H:i:s.u', $utime).'<br>'; // 1800-01-01 00:00:00.123000
$utime = 1476072000.123000;
echo udate('Y-m-d H:i:s.u', $utime).'<br>'; // 2016-10-10 12:00:00.123000
//1992年是好的
$d=new DateTime("1992-05-30 15:50:00",new DateTimeZone('UTC'));
echo $d->format("Y-m-d H:i:s")."\n";//1992-05-30 15:50:00
$d->setTimezone(new DateTimeZone('PRC'));
echo $d->format("Y-m-d H:i:s")."\n";//1992-05-30 23:50:00
//1991年出现错误,时区是9小时?
$d=new DateTime("1991-05-30 15:50:00",new DateTimeZone('UTC'));
echo $d->format("Y-m-d H:i:s")."\n";//1991-05-30 15:50:00
$d->setTimezone(new DateTimeZone('PRC'));
echo $d->format("Y-m-d H:i:s")."\n";//1991-05-31 00:50:00
也许这就是导致我写的MS_Date函数出现“1940年和1986-1991中间时间有些转换会有偏差”的原因,坑爹不是
这个错误还是我写完EDate类测试好之后抽空发现的,EDate类已经写好了,完全满足要求了,把新的MS_Date代码贴下面,这个是完是自己代码计算的,没有用PHP自带的时间方法,如果谁要用就拿去用好了。
类似的用法
MS_Date(-30610252800000)//1000-01-01 00:00
MS_Date(32503651200000)//3000-01-01 00:00
MS_Date(1475925060000)//2016-10-08 19:11
static function MS_Date($ms){
$z=8;
$ms+=$z*60*60*1000;
$t=$ms;
$ss=intval(fmod($t,1000));
$t=floor($t/1000);
$s=intval(fmod($t,60));
$t=floor($t/60);
$m=intval(fmod($t,60));
$t=floor($t/60);
$h=intval(fmod($t,24));
$t=ceil($t/24);
$day=intval($t);
if($ms<0){
$h=24+$h;
$m=60+$m;
$s=60+$s;
$ss=1000+$ss;
if($ss==1000){
$ss=0;
}
if($s==60){
$s=0;
}
if($m==60){
$m=0;
}
if($h==24){
$h=0;
}
}
if($h==0){
$day++;
}
$day=719527+$day;//day=0;for(var i=1;i<=1970;i++){if(i%400==0||i%100>0&&i%4==0){day+=366}else{day+=365}};day
$y=0;
$ydPrev=0;
while(true){
$y=$y+intval($day/366);
$day=$day%366;
$yd=$y-(intval($y/4)-intval($y/100)+intval($y/400));
$day+=$yd-$ydPrev;
if($day==366){
if($ms>0 && EDate::IsLeapYear($y+1)){
$day=0;
$y++;
break;
}
}else if($day==365){
if($ms>0 && !EDate::IsLeapYear($y+1)){
$day=0;
$y++;
}
break;
}else if($day<365){
break;
}
$ydPrev=$yd;
}
$Y=$y;
$M=0;
$D=0;
while(true){
$isLeap=EDate::IsLeapYear($Y);
if($isLeap){
$day++;
}
if($day==0){
if($ms<0){
$M=1;
$D=1;
}else{
$Y--;
$M=12;
$D=31;
}
break;
}else if($day>=60 && $isLeap){
if($day>60){
$day--;
}else if($day==60){
$M=2;
$D=29;
break;
}
}
if($day<=31){
$M=1;
$D=$day;
}else if($day<=59){
$M=2;
$D=$day-31;
}else if($day<=90){
$M=3;
$D=$day-59;
}else if($day<=120){
$M=4;
$D=$day-90;
}else if($day<=151){
$M=5;
$D=$day-120;
}else if($day<=181){
$M=6;
$D=$day-151;
}else if($day<=212){
$M=7;
$D=$day-181;
}else if($day<=243){
$M=8;
$D=$day-212;
}else if($day<=273){
$M=9;
$D=$day-243;
}else if($day<=304){
$M=10;
$D=$day-273;
}else if($day<=334){
$M=11;
$D=$day-304;
}else{
$M=12;
$D=$day-334;
}
break;
}
$Y=substr('000'.$Y,-4);
$M=substr('0'.$M,-2);
$D=substr('0'.$D,-2);
$h=substr('0'.$h,-2);
$m=substr('0'.$m,-2);
$s=substr('0'.$s,-2);
$ss=substr('00000'.$ss*1000,-6);
$date=new DateTime($Y.'-'.$M.'-'.$D.'T'.$h.':'.$m.':'.$s.'.'.$ss.'Z', new DateTimeZone('PRC'));
return $date;
}
最后还是要请教一下:
1、PHP时间日期 上面需求这样的处理是否有什么需要规避的细节
2、别人时间日期和毫秒数转换如何处理
3、有没有什么现成可用的东西能拿过来直接用
function microtime_format($tag, $time)
{
list($usec, $sec) = explode(".", $time);
$date = date($tag,$usec);
return str_replace('x', $sec, $date);
}
microtime_format('Y年m月d日 H时i分s秒 x毫秒', 1270626578.66000000);
round(microtime(true)*1000);
其实如果不纠,结秒*1000也可以(丢失了时间的毫秒部分,一秒可以做很多事情嘞),就是感觉不舒服,网页传过来的值可以达到毫秒精度,php里一处理就丢了,这个就不提了是好的。
现在问题在毫秒数转成时间上,比如-5364691199877成时间1800-01-01 0:0:0.123,有没有什么好方法
电脑上装的PHP Version 5.6.14
echo ceil(microtime(true) * 1000);