Surpassing MySQL's TIME value limit of 838:59:59

前端 未结 6 525
南旧
南旧 2020-12-01 14:54

The title might be a bit confusing so allow me to explain. I\'m using a table to record my work logs. Every day I\'ll create an entry stating from what time to what time I h

相关标签:
6条回答
  • 2020-12-01 15:31

    Counting the days separately is enough.
    Here's the concatenation I used.

    I illustrated with a fully copy/pastable example to ease the understanding of the limit we hit (TIME format's max value)
    A free unicorn is bundled to simplify comma management

    SELECT 'pq7~' AS unicorn
    #######################
    ##  Expected result  ##
    #######################
    ## Total, formatted as days:hh:mm:ss ##
      ,CONCAT(
        FLOOR(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') / 86400)
        , ':'
        , SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') % 86400)
      ) AS Real_expected_result
    

    #########################
    ## Calculation details ##
    #########################
    ## Extracted days from diff ##
      ,FLOOR(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') / 86400) AS Real_days
    ## Extracted Hours/minutes/seconds from diff ##
      ,SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') % 86400) AS Real_hours_minutes_seconds
    

    ###################################
    ## Demo of wrong values returned ##
    ###################################
      ,TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') AS Real_seconds_diff
    
    ## WRONG value returned. 5.64M is truncated to 3.02 ! ##
      ,TIME_TO_SEC(SEC_TO_TIME(5644119)) AS WRONG_result
    
    ## Result is effectively limited to 838h59m59s ##
      ,SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24')) AS Limit_hit
    
    ## Lights on said limit ##
      ,SEC_TO_TIME( 3020398) AS Limit_value_check1
      ,SEC_TO_TIME( 3020400) AS Limit_value_check2
    
    0 讨论(0)
  • 2020-12-01 15:36

    I'd just retrieve the total number of seconds worked, and convert to hours/minutes as required in the presentation layer of my application (it is, after all, a simple case of division by 60):

    <?
      $dbh = new PDO("mysql:dbname=$dbname", $username, $password);
      $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
    
      $qry = $dbh->prepare('
        SELECT SUM(TIME_TO_SEC(entry_end_time)-TIME_TO_SEC(entry_start_time))
        FROM   entry 
        WHERE  entry_date BETWEEN :start_date AND :end_date
           AND user_id = :user_id
      ');
    
      $qry->execute([
        ':start_date' => '2012-01-01',
        ':end_date'   => '2012-12-31',
        ':user_id'    => 3
      ]);
    
      list ($totalMins, $remngSecs) = gmp_div_qr($qry->fetchColumn(), 60);
      list ($totalHour, $remngMins) = gmp_div_qr($totalMins, 60);
    
      echo "Worked a total of $totalHour:$remngMins:$remngSecs.";
    ?>
    
    0 讨论(0)
  • 2020-12-01 15:36

    First calculating the days difference then multiply it with 24*60*60 to convert it into seconds then add to it time_to_sec value result

    DATEDIFF(start_date,end_date)*24*60*60 + TIME_TO_SEC(TIMEDIFF(TIME(start_date),TIME(end_date))) 
    AS sec_diff
    

    For more details check codebucket- Surpassing time_to_sec() function maximum limit

    0 讨论(0)
  • 2020-12-01 15:40

    Some simple math can do the trick,I hardcoded a random number of seconds(10000000)

    SELECT CONCAT(FLOOR(10000000/3600),':',FLOOR((10000000%3600)/60),':',(10000000%3600)%60)
    

    Fiddle

    2777:46:40
    
    0 讨论(0)
  • 2020-12-01 15:40
    select  concat(truncate(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini)))/3600,0), ':', 
    TIME_FORMAT(sec_to_time(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini))) - truncate(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini)))/3600,0)*3600), '%i:%s'))
    as hms from  tb_XXXXXX
    
    0 讨论(0)
  • 2020-12-01 15:49

    Have a look at timestampdiff which doesn't have the TIME limitation. I.e. something like (untested):

    SELECT CONCAT(
            TIMESTAMPDIFF(HOURS, entry_end_time, entry_start_time), 
            ":",
            MOD(TIMESTAMPDIFF(MINUTES, entry_end_time, entry_start_time),60)
          )
    AS total FROM entry 
    WHERE entry_date BETWEEN '2012-01-01' AND '2012-12-31' AND user_id = 3
    

    The concats not ideal, I'm sure there will be a more elegant solution.

    0 讨论(0)
提交回复
热议问题