2016-03-26 36 views
0

我有一个用PHP编写的界面,用于记录员工工作时间。为了计算换档差异,我想添加一个新算法来测量在特定小时之间工作的时间量。我使用MySQL的unix_time()作为时间戳。计算两次之间的部分时间

示例:员工从下午6点工作到凌晨2点。在晚上10点到上午6点之间有一个有偿转换差。员工收到4小时的正常工资,4小时的工资+差额。

$start_time = 1459015200; // 18:00 03/26/2016 
$end_time = 1459044000; // 02:00 03/27/2016 

$diff_start = mktime('22','00','00','3','26','2016'); 
$diff_end = mktime('06','00','00','3','27','2016'); 

我想写给大集的时间可能工作,一个脚本,计算时间晚上10点至下午6点之间工作的量。这个答案完成似乎做我在找什么,除了在MySQL:Calculating time difference before 6am and after 10pm in MySQL

这个答案是类似于我的问题:Calculate the number of hours in a given timeframe between two datetimes,但依赖于一个循环。鉴于时间以秒为单位输入,基于unix_time,我假设使用一个循环将需要一秒增量(这意味着每周有数千条记录通过循环进行很多次循环)。

有没有一种有效的方法(如MySQL示例)在PHP中执行此操作,而不需要像第二个答案中建议的那样循环每增加一秒/每分钟/小时?

+0

22-18 + 6-2?差速器开始减档开始,再加上差速器结束减去换档结束?也许我没有跟着。 – bishop

+1

dst切换期间转换!决定命运的时间。 – Jack

+0

你不是在开玩笑。也许有一天我会花时间转换成不同的格式。 – thebarless

回答

1

有:使用阵列与特殊形式的键。首先

mktime('22','00','00','3','26','2016') => 1459026000 
mktime('06','00','00','3','27','2016') => 1459051200 

现在建立你差阵列:

$shifts=array (
    0 => 0, 
    1459026000 => $diff, 
    1459051200 => 0 
); 

这意味着,从时间戳0..1459025999的差是0,从1459026000到1459051199的差是$diff和1459051200至无限再次为0。当然,你真正的换班表会更大。

现在通过这个数组soemthing像foreach ($shifts as $start=>$differential)刚好运行一次,并比较$start$start_time$end_time,这些情况:

  • $start>$end_time:忽略,这是在未来
  • $start<$start_time:忽略,这是过去的
  • else:计算秒数并使用$差分
+0

当你有一个迭代$ diff = 1和$ start <$ start_time时,你不知道是否$ nextStart> $ start_time – Jack

+0

@Jack - 1,所以这是行不通的。$ diff的值是对于时间计算来说不重要 - 它可以是-3.1415而不改变算法; 2.虽然我对**下一个**开始一无所知,但我知道关于**前一个**开始的所有内容,这是数组第一行('0 => 0')的基本原理。 ,所以我在接下来处理这个案例,而不是在'else'分支的前一个迭代中。 –

+0

我没有得到算法。假设您有$ start_time = 1459029600(11:00 PM)和$ end_time = 1459036800(01:00 AM)。根据您陈述的情况,您的所有迭代都应该被忽略。 – Jack

0

喜欢这个问题。看起来像面试问题。我花了一些时间来实现这个效率,没有循环。首先我执行以下操作:

function date_intersection($a_from, $a_to, $b_from, $b_to); 

返回两个时间范围之间的秒数。

然后,与该移位长度不能超过24小时的限制,我需要构建两个范围块:

  • 这是您的当前时移
  • 的之前与差动范围范围具有差分这是后

它之后,溶液是直接的:

$total = $end_time - $start_time; 
$differ = date_intersection($b1s, $b1e, $start_time, $end_time) + date_intersection($b2s, $b2e, $start_time, $end_time); 
$normal = $total-$differ; 

有效解决此问题涉及不使用mktime()或date()来提取部分日期,因为您真的可以通过unix-timestamp解决模块运算符的问题。但是照顾DST真的让它变得复杂。 如果你今晚只问过这个问题,我会回答之前(不正确):)

+0

我欣赏后续文章。我不确定我是否理解你的'date_intersection'函数的重点。有东西被切掉了吗?另外,$ b1s/e&$ b2s/e的目的是什么? – thebarless

+0

我认为没有什么时间差异开始/结束,什么时间工作班次开始/结束的限制。如果你有后者,问题是微不足道的,因为你可以预先计算所有可能的变化的差异。(date_intersection(10,15,12,22)== 3)和(b1s = block_1_start)。 – Jack