【问题标题】:get timestamp minimum and maximum value for a given month in PHP获取PHP中给定月份的时间戳最小值和最大值
【发布时间】:2020-09-08 21:17:05
【问题描述】:

我有什么:

我有一个动态加载用户任务的 php - mysql - jquery/ajax 调度程序。为了显示用户任务的开始和结束时间,我将值作为unix timestamp 存储在我的MYSQl database 中。

例如:

Task start: 1599026400 = 2020-09-02 08:00:00
Task end: 1599057000 = 2020-09-02 16:30:00

为了获取数据库中一个月的所有任务,我需要该特定月份的最小和最大 timestamp

Min date: 1598911200 = 2020-09-01 00:00:00 
Max date: 1601503199 = 2020-09-30 23:59:59

问题: 我正在寻找最干净/最快速的方式来获取这些数据。

$result = time();                             // current timestamp (is created by a jquery date-picker)
$time = strtotime(date('Y-m-d', $result));    // create a new date to remove the original time (H:i:s)
echo strtotime(date('Y-m-01 H:i:s', $time));  // display first day of month, time = 00:00:00
echo strtotime(date('Y-m-t H:i:s', $time)) + 86399; // display last day of month (add 86399 seconds = 23:59:59)

有没有更有效的方法来达到这个结果?

【问题讨论】:

  • 您所指的这个问题是关于从时间戳中减去 5-10 分钟。提到的问题也是关于 MYSQL 而不是 PHP。
  • 在获取早于“month before”和更年轻的“month after”的数据时,您是否对查询进行了计时。这样你就不需要任何 php 计算时间戳了?
  • 将时间存储为 DateTime(Mysql 类型)不是更灵活吗?这些是人类可读的,您的查询可以以更全面的方式构建:WHERE yourColumn BETWEEN '2020-09-01' AND '2020-10-01.仅提取 yourColumn 引用星期二的那些记录甚至会很简单。 Unix时间戳会给你带来很多工作。当然,您的问题与此无关,但在某些时候您可能会在数据上遇到此类问题,然后转换可能为时已晚

标签: php timestamp


【解决方案1】:

这样就可以了,不需要加86399秒:

echo strtotime(date('Y-m-01 00:00:00'));  // display first day of month, time = 00:00:00
echo strtotime(date('Y-m-t 23:59:59'));   // display last day & time of month, time = 23:59:59

【讨论】:

    【解决方案2】:

    除了将日期戳转换为指定一个月的第一天/最后一天的 Unix 时间戳之外,我没有看到其他更快的解决方案。

    $month_start = strtotime(date('Y-m-01 00:00:00')); //1598911200
    $month_end = strtotime(date('Y-m-t 23:59:59')); //1601503199
    

    但在这种情况下,您会收到一个通知。这会根据服务器的时区转换日期。因此,如果您在欧洲/柏林地区,时间戳将与 UTC 相差 2 小时。如果要获取 UTC 时间戳,则必须转换时区。您可以使用 date() 函数来完成此操作,但我更喜欢使用 DateTime 对象进行操作。

    $date = new DateTime(date('Y-m-01 00:00:00'), new DateTimeZone('UTC'));
    $month_start_utc = $date->format('U'); //1598918400
    
    $date = new DateTime(date('Y-m-t 23:59:59'), new DateTimeZone('UTC'));
    $month_end_utc = $date->format('U'); //1601510399
    

    【讨论】:

      【解决方案3】:

      您可以使用 DateTime 对象来获取该月的第一天和最后一天:

      $time = time(); // or whatever timestamp you want to use
      
      $firstDayTime = (new \DateTime())
          ->setTimestamp($time)
          ->setTime(0, 0, 0)
          ->modify('first day of this month')
          ->format('U')
      ;
      
      $lastDayTime = (new \DateTime())
          ->setTimestamp($time)
          ->setTime(23, 59, 59)
          ->modify('last day of this month')
          ->format('U')
      ;
      

      但不确定它是否更干净或更快......

      【讨论】:

      • DateTime 在构造函数中将当前时间作为默认值。你不需要在setTime()方法中重复它。
      【解决方案4】:

      我尝试了几种方法,您可以在那里找到结果: http://sandbox.onlinephpfunctions.com/code/dd42088f7086a9986b1e295fb588f98714fddf2e

      最快的方法是:

      function func_5(){
        $month=date('n');
        $year=date('Y');
        $start=strtotime($year.'-'.$month.'-01 00:00:00');
        $number_of_days=cal_days_in_month(CAL_GREGORIAN,$month,$year);
        return [$start, $start+$number_of_days*86400-1];
      }
      

      【讨论】:

        【解决方案5】:

        您可以为此使用 MySQL,并且只为您的查询传递月份。

        在此处查看工作示例:https://paiza.io/projects/pvZ6tl2mRE1FJaweyT37Yw?language=mysql

        这样你就不需要在 PHP 中进行任何计算了。

        -- create a table
        CREATE TABLE task (
          id INTEGER PRIMARY KEY,
          start timestamp NOT NULL,
          end timestamp NOT NULL
        );
        -- insert some values
        INSERT INTO task VALUES (1, '2020-09-01 00:00:01', '2020-09-01 20:00:01');
        INSERT INTO task VALUES (2, '2020-09-15 00:00:01', '2020-09-16 12:00:01');
        INSERT INTO task VALUES (3, '2020-09-30 00:00:01', '2020-09-30 23:59:59');
        INSERT INTO task VALUES (4, '2020-08-31 23:00:01', '2020-08-31 23:59:01');
        INSERT INTO task VALUES (5, '2020-10-01 00:00:01', '2020-10-02 01:00:01');
        
        -- fetch some values
        SELECT * FROM task WHERE MONTH(start) = 9 ;
        

        【讨论】:

          【解决方案6】:

          所有提供的答案仅给出当前月份的解决方案。但是,如果您想要任何给定月份的最小值/最大值,我会使用 DateInterval 操作日期

          function min_max_timestamp(int $year, int $month): array {
              $start = new DateTimeImmutable(date("$year-$month-01 00:00:00"), new DateTimeZone('UTC'));
              $end = $start->add(new DateInterval('P1M'))
                  ->sub(new DateInterval('PT1S'));
          
              $month_start_utc = $start->format('U');
              $month_end_utc = $end->format('U');
          
              return [$month_start_utc, $month_end_utc];
          }
          
          list($min, $max) = min_max_timestamp(2020, 9);
          

          如果您将 SQL 查询更改为使用少于 start >= 'first of month' AND start < 'first of next month' 的次数,则可以跳过 ->sub(new DateInterval('PT1S')) 步骤

          【讨论】:

            【解决方案7】:

            您有三种方法可以做到这一点。 使用PHPDate/Time函数

            $date = '2020-09-02 08:00:00';
            $dateParts = date_parse($date);
            $date = $dateParts['year']."-".$dateParts['month']."-01 00:00:00";
            $startDate = date_create($date);
            $endDate = date_sub(date_add(date_create($date), date_interval_create_from_date_string('1 month')),date_interval_create_from_date_string('1 second'));
            print_r(['start' => date_timestamp_get($startDate), 'end' => date_timestamp_get($endDate)]);
            Array
            (
                [start] => 1598943600
                [end] => 1601535599
            )
            

            通过使用MySQL Date/Time 函数

            SELECT DATE_SUB('2020-09-02 08:00:00',INTERVAL CONCAT(DAY('2020-09-02 08:00:00')-1,' ',HOUR('2020-09-02 08:00:00'),':',MINUTE('2020-09-02 08:00:00'),':',SECOND('2020-09-02 08:00:00')) DAY_SECOND), DATE_SUB(DATE_ADD(DATE_SUB('2020-09-02 08:00:00',INTERVAL CONCAT(DAY('2020-09-02 08:00:00')-1,' ',HOUR('2020-09-02 08:00:00'),':',MINUTE('2020-09-02 08:00:00'),':',SECOND('2020-09-02 08:00:00')) DAY_SECOND), INTERVAL 1 MONTH), INTERVAL 1 SECOND);
            
            OUTPUT
            2020-09-01 00:00:00  | 2020-09-30 23:59:59
            

            通过在客户端执行完全相同的操作并使用 ajax 而不是日期发送时间戳。我认为在这种情况下,这不是您想要的,因为它需要对您的代码进行更多更改(前端、后端)。尽管如此,这里还是使用Javascript 的类似方式。

            let pickDate = new Date('2020-09-02 08:01:32');
            let startDate = new Date(pickDate.getUTCFullYear()+"-"+(pickDate.getUTCMonth()+1)+"-01");
            startDate.setHours(-startDate.getTimezoneOffset()/60);
            let endDate = new Date(startDate);
            endDate.setMonth(startDate.getMonth()+1);
            endDate.setSeconds(-1);
            console.log([startDate,endDate]);
            console.log([startDate.getTime()/1000,endDate.getTime()/1000]);

            【讨论】:

            • 使用 DateTime 对象的糟糕例子。
            • @Tajni 如果您的意思是应该设置TimeZone 是的,应该设置。但是在这种情况下,假设存储在数据库中的Date 是以尊重可能存在的服务器-客户端Timezone 差异的方式完成的。感谢您的评论,但我认为这不是一个糟糕的例子。
            • @Tajni 我认为当我开始写这个答案时你的答案已经存在。所以我不得不写一些不同的东西,你不觉得吗?!以我的名义写一个与您的答案非常相似的答案有多合乎道德?我有点认为在一个问题中有多个答案的目的是在每个答案中提供不同的东西。
            • @Tajni 正如你所写的那样有正确的答案是 SO 的重点。。这是正确答案sandbox.onlinephpfunctions.com/code/…。很抱歉您发现它晦涩。您不理解为什么其余答案存在这一事实,并不意味着其他可能阅读或已经阅读过答案的人也不理解。
            • @Tajni 这取自问题... 我有一个动态加载的用户任务的 php - mysql - jquery/ajax 调度程序。.
            【解决方案8】:

            使用 microtime 检查,您的解决方案可能不会更整洁,但比使用 DateTime 更快:

            0.00017309188842773
            0.00022792816162109
            0.00019717216491699
            0.00018095970153809
            0.00018000602722168
            0.00018596649169922
            

            VS

            0.00023007392883301
            0.00029492378234863
            0.00026392936706543
            0.00024795532226562
            0.00028395652770996
            0.0002589225769043
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-04-03
              • 1970-01-01
              • 2019-01-16
              • 2017-05-15
              • 2016-09-18
              • 2011-08-16
              • 1970-01-01
              • 2017-05-12
              相关资源
              最近更新 更多