Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/255.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何将unix时间戳上下舍入到最接近的半小时?_Php_Datetime_Unix Timestamp - Fatal编程技术网

Php 如何将unix时间戳上下舍入到最接近的半小时?

Php 如何将unix时间戳上下舍入到最接近的半小时?,php,datetime,unix-timestamp,Php,Datetime,Unix Timestamp,好的,我正在我的CRM系统中开发一个日历应用程序,我需要找到半个小时的上限和下限,这半个小时是某人在日历中输入事件的时间戳的上限和下限,以便在数据库上运行一些SQL,以确定他们是否已经在该时间段内预订了某些内容 例如,我的时间戳为1330518155=2012年2月29日16:22:35 GMT+4 所以我需要得到1330516800和1330518600,它们分别等于16:00和16:30 如果有人有任何想法或认为我正在以一种愚蠢的方式开发日历,请告诉我!这是我第一次在这样一个任务涉及如此多的

好的,我正在我的CRM系统中开发一个日历应用程序,我需要找到半个小时的上限和下限,这半个小时是某人在日历中输入事件的时间戳的上限和下限,以便在数据库上运行一些SQL,以确定他们是否已经在该时间段内预订了某些内容

例如,我的时间戳为1330518155=2012年2月29日16:22:35 GMT+4 所以我需要得到1330516800和1330518600,它们分别等于16:00和16:30


如果有人有任何想法或认为我正在以一种愚蠢的方式开发日历,请告诉我!这是我第一次在这样一个任务涉及如此多的时间和日期,所以任何建议感谢工作

您可能知道,UNIX时间戳是秒数,因此减/加
1800
(秒数为
30
分钟),您将得到所需的结果。

您可以使用模运算符

$time -= $time % 3600; // nearest hour (always rounds down)

希望这足以为您指出正确的方向,如果没有,请添加注释,我将尝试制作一个更具体的示例。

我将使用
localtime
mktime
函数

$localtime = localtime($time, true);
$localtime['tm_sec'] = 0;
$localtime['tm_min'] = 30;
$time = mktime($localtime);
使用模

$prev = 1330518155 - (1330518155 % 1800);
$next = $prev + 1800;

模运算符给出除法的剩余部分。

PHP确实有一个DateTime类和它提供的一整套方法。如果您愿意,可以使用这些函数,但我发现使用内置的
date()
strotime()
函数更容易

以下是我的解决方案:

// Assume $timestamp has the original timestamp, i.e. 2012-03-09 16:23:41

$day = date( 'Y-m-d', $timestamp ); // $day is now "2012-03-09"
$hour = (int)date( 'H', $timestamp ); // $hour is now (int)16
$minute = (int)date( 'i', $timestamp ); // $minute is now (int)23

if( $minute < 30 ){
  $windowStart = strtotime( "$day $hour:00:00" );
  $windowEnd   = strtotime( "$day $hour:30:00" );
} else {
  $windowStart = strtotime( "$day $hour:30:00" );
  if( ++$hour > 23 ){
    // if we crossed midnight, fix the date and set the hour to 00
    $day = date( 'Y-m-d', $timestamp + (24*60*60) );
    $hour = '00';
  }
  $windowEnd   = strtotime( "$day $hour:00:00" );
}

// Now $windowStart and $windowEnd are the unix timestamps of your endpoints
//假设$timestamp具有原始时间戳,即2012-03-09 16:23:41
$day=日期('Y-m-d',$timestamp);//$现在是“2012-03-09”
$hour=(int)日期('H',$timestamp);//$现在是(国际)16小时
$minute=(int)日期('i',$timestamp);//$分钟现在是(国际)23
如果($min<30){
$windowStart=strotime($day$hour:00:00);
$windowEnd=strottime($day$hour:30:00);
}否则{
$windowStart=strottime($day$hour:30:00);
如果(+$hour>23){
//如果我们过了午夜,确定日期并将小时设置为00
$day=日期('Y-m-d',$timestamp+(24*60*60));
$hour='00';
}
$windowEnd=strotime($day$hour:00:00);
}
//现在,$windowStart和$windowEnd是端点的unix时间戳
在这方面可以做一些改进,但这是基本的核心

[编辑:更正了我的变量名!]


[编辑:我重新审视了这个答案,因为让我尴尬的是,我意识到它没有正确处理一天中的最后半个小时。我已经解决了这个问题。请注意,
$day
是通过在时间戳上添加一天的秒数来解决的——这样做意味着我们不必担心跨越月边界、闰日等。请注意因为PHP将为我们正确设置格式。]

我没有清楚地阅读问题,但对于那些不需要两者之间的范围的人,此代码将精确到半小时。使用SenorAmor的一些代码。道具和他疯狂优雅的解决方案来解决正确的问题

$time = 1330518155; //Or whatever your time is in unix timestamp

//Store how many seconds long our rounding interval is
//1800 equals one half hour
//Change this to whatever interval to round by
$INTERVAL_SECONDS = 1800;  //30*60

//Find how far off the prior interval we are
$offset = ($time % $INTERVAL_SECONDS); 

//Removing this offset takes us to the "round down" half hour
$rounded = $time - $offset; 

//Now add the full interval if we should have rounded up
if($offset > ($INTERVAL_SECONDS/2)){
  $nearestInterval = $rounded + $INTERVAL_SECONDS;
}
else{
  $nearestInterval = $rounded 
}

如果需要获取当前时间,然后应用时间的四舍五入(向下),我将执行以下操作:

$now = date('U');
$offset = ($now % 1800);
$now = $now-$offset;
for ($i = 0;$i < 24; $i++)
{
    echo date('g:i',$now);
    $now += 1800;
}
$now=date('U');
$offset=($now%1800);
$now=$now-$offset;
对于($i=0;$i<24;$i++)
{
回音日期('g:i',$now);
$now+=1800;
}

或者,您可以通过添加偏移量进行取整,并执行一些不只是回显时间的操作。for循环然后显示12小时的增量。我在最近的一个项目中使用了上述内容。

这与我的最佳工作相去甚远……但这里有一些用于处理字符串或unix时间戳的函数

/**
 * Takes a timestamp like "2016-10-01 17:59:01" and returns "2016-10-01 18:00"
 * Note: assumes timestamp is in UTC
 * 
 * @param $timestampString - a valid string which will be converted to unix with time()
 * @param int $mins - interval to round to (ex: 15, 30, 60);
 * @param string $format - the format to return the timestamp default is Y-m-d H:i
 * @return bool|string
 */
function roundTimeString( $timestampString, $mins = 30, $format="Y-m-d H:i") {
    return gmdate( $format, roundTimeUnix( time($timestampString), $mins ));
}

/**
 * Rounds the time to the nearest minute interval, example: 15 would round times to 0, 15, 30,45
 * if $mins = 60, 1:00, 2:00
 * @param $unixTimestamp
 * @param int $mins
 * @return mixed
 */
function roundTimeUnix( $unixTimestamp, $mins = 30 ) {
    $roundSecs = $mins*60;
    $offset = $unixTimestamp % $roundSecs;
    $prev = $unixTimestamp - $offset;
    if( $offset > $roundSecs/2 ) {
        return $prev + $roundSecs;
    }
    return $prev;
}

这是一个使用
DateTimeInterface
并保留时区信息等的解决方案。它还将处理与格林尼治标准时间相差不超过30分钟的时区(例如
亚洲/加德满都


不过,您需要先创建DateTime对象-可能使用类似于
$DateTime=new DateTimeImmutable('@.$timestamp)
的方法。您还可以在构造函数中设置时区。

这里有一个更具语义的方法,适用于那些必须在一天中的某些时间创建其中一些对象的人

$time = strtotime(date('Y-m-d H:00:00'));

您可以将该
H
更改为任何0-23个数字,这样您就可以舍入到当天的该小时。

尝试使用手动中的功能-应该会有所帮助,您可以很容易地从时间戳中添加或删除任何时间量。这与时间和日期有什么关系?这是一个简单的数学,但不是真正的舍入,是吗?这将找到3前0分钟和后30分钟,而不是“按小时”和“按半小时”限定时间。请再看一次他的例子。这将找到从小时开始的秒数,但这只是问题的一部分,因为如果分钟数>=30,时间括号是H:30到H+1:00,因为我们除以1800,它将给出从最后半小时开始的秒数增量(1:00,1:30,2:00,2:30,等等)。如果是1:30:01,模运算将返回1,$prev将是1:30。添加1800秒将使$next等于2:00。同样,如果是1:29:59,模运算将是1799,$prev将是1:00。同样,添加1800将使$next为1:30。有时你只是想做一些简单的事情,然后寻找一个函数来做一些基本的算术metic!我真的很喜欢这是多么优雅。它不仅是用算术完成的,而且在任何时区都能工作(除了查塔姆群岛和尼泊尔,这两个时区只有15分钟而不是30分钟)。ModuleNet!哈哈哈
$time = strtotime(date('Y-m-d H:00:00'));