【问题标题】:How to round unix timestamp up and down to nearest half hour?如何将unix时间戳上下舍入到最接近的半小时?
【发布时间】:2012-03-27 05:36:22
【问题描述】:

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

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

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

【问题讨论】:

  • 尝试使用手册中的功能 - php.net/manual/en/function.strtotime.php - 应该会有所帮助,您可以非常轻松地从时间戳中添加或删除任意数量的时间。
  • 这与时间和日期有什么关系?这是简单的数学

标签: php datetime unix-timestamp


【解决方案1】:

您可能知道,UNIX 时间戳是秒数,因此减去/添加 180030 分钟中的秒数),您将得到所需的结果。

【讨论】:

  • 这并不是真正的四舍五入,是吗?
  • 这将找到之前 30 分钟和之后 30 分钟,而不是限定时间的“整点”和“半小时”。请再看看他的例子。
【解决方案2】:

您可以使用模运算符。

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

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

【讨论】:

    【解决方案3】:

    我会使用localtimemktime 函数。

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

    【讨论】:

      【解决方案4】:

      使用模数。

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

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

      【讨论】:

      • 这将找到自小时以来的秒数,但这只是问题的一部分,因为如果分钟数 >= 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。
      • 如此简单,有时您只是想多想一些事情并寻找一个函数来做一些基本的算术!
      • 我真的很喜欢它的优雅。它不仅只用算术完成,而且不受时区限制(查塔姆群岛和尼泊尔除外,它们是仅有的两个时区相差 15 分钟而不是 30 分钟)。
      • 模块化!哈哈哈哈
      【解决方案5】:

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

      这是我的解决方案:

      // 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
      

      可以对此进行一些改进,但这是基本核心。

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

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

      【讨论】:

        【解决方案6】:

        我没有清楚地阅读问题,但是对于那些不需要两者之间范围的人,此代码将四舍五入到最接近的半小时。使用一些 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 
        }
        

        【讨论】:

          【解决方案7】:

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

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

          或者您可以通过添加偏移量来进行四舍五入,并且做的不仅仅是回显时间。然后 for 循环显示 12 小时的增量。我在最近的一个项目中使用了上述内容。

          【讨论】:

            【解决方案8】:

            远非我的最佳作品……但这里有一些用于处理字符串或 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;
            }
            

            【讨论】:

              【解决方案9】:

              这是一个使用 DateTimeInterface 并保留时区信息等的解决方案。还将处理与 GMT 偏移量不是 30 分钟倍数的时区(例如 Asia/Kathmandu)。

              /**
               * Return a DateTimeInterface object that is rounded down to the nearest half hour.
               * @param \DateTimeInterface $dateTime
               * @return \DateTimeInterface
               * @throws \UnexpectedValueException if the $dateTime object is an unknown type
               */
              function roundToHalfHour(\DateTimeInterface $dateTime)
              {
                  $hours = (int)$dateTime->format('H');
                  $minutes = $dateTime->format('i');
              
                  # Round down to the last half hour period
                  $minutes = $minutes >= 30 ? 30 : 0;
              
                  if ($dateTime instanceof \DateTimeImmutable) {
                      return $dateTime->setTime($hours, $minutes);
                  } elseif ($dateTime instanceof \DateTime) {
                      // Don't change the object that was passed in, but return a new object
                      $dateTime = clone $dateTime;
                      $dateTime->setTime($hours, $minutes);
                      return $dateTime;
                  }
                  throw new UnexpectedValueException('Unexpected DateTimeInterface object');
              }
              

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

              【讨论】:

                【解决方案10】:

                对于那些必须制作其中一些的人来说,这是一种更具语义化的方法,也许在一天中的某些时间。

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

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

                【讨论】:

                  猜你喜欢
                  • 2017-12-02
                  • 2016-05-31
                  • 1970-01-01
                  • 2018-10-25
                  • 2023-03-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-12-11
                  相关资源
                  最近更新 更多