<?php

class WorkTime
{
// 定义工作日 [1, 2, 3, 4, 5, 6, 0]
public $week_workingday = [1, 2, 3, 4, 5]; // 定义上下班时间
public $on_duty_time = '9:00:00';
public $off_duty_time = '18:00:00'; //每天工作时长
public $oneday_hours = null; public function __construct()
{
if (empty($this->oneday_hours)) {
$this->oneday_hours = $this->off_duty_time - $this->on_duty_time;
}
} public function get_working_hours(int $start_time, int $over_time)
{
// 如果工作日列表为空 返回0
$workingdays = $this->workingdays($start_time, $over_time); if (empty($workingdays)) {
return 0;
} // 如果开始时间不是工作日,将开始时间调整为第一个工作日的上班时间
// 如果截止时间不是工作日,将开始时间调整为最后一个工作日的下班时间
if (!in_array(date('Y/m/d', $start_time), $workingdays)) {
$start_time = strtotime($workingdays[0] . ' ' . $this->on_duty_time);
} if (!in_array(date('Y/m/d', $over_time), $workingdays)) {
$over_time = strtotime(end($workingdays) . ' ' . $this->off_duty_time);
} // 如果开始时间与截止时间是同一天,直接计算
// 反之分别计算开始时间与截止时间
if (date('Y/m/d', $start_time) == date('Y/m/d', $over_time)) {
$sec = $over_time - $start_time;
if ($sec > 3600 * $this->oneday_hours) {
$sec = 3600 * $this->oneday_hours;
}
// 昨天到了计算秒数
} else {
// 计算开始日工作时间
$start_day_sec = strtotime($workingdays[0] . ' ' . $this->off_duty_time) - $start_time;
if ($start_day_sec > 3600 * $this->oneday_hours) {
$start_day_sec = 3600 * $this->oneday_hours;
}
// 计算截止日工作时间
$over_day_sec = $over_time - strtotime(end($workingdays) . ' ' . $this->on_duty_time);
if ($over_day_sec > 3600 * $this->oneday_hours) {
$over_day_sec = 3600 * $this->oneday_hours;
} $all_day_sec = ((count($workingdays) - 2) * $this->oneday_hours) * 3600;
$sec = $start_day_sec + $over_day_sec + $all_day_sec;
} return $sec / 3600;
} # 计算工作日(包含开始与截止日期)
protected function workingdays($start_time, $over_time)
{
$start_time = strtotime('-1 day', $start_time);
$over_time = strtotime('-1 day', $over_time); $new_workingdays = $this->new_workingdays();
$new_holidays = $this->new_holidays();
$workingdays = []; while ($start_time < $over_time) {
$start_time = strtotime('+1 day', $start_time);
$is_holidays = in_array(date('w', $start_time), $this->week_workingday) && !in_array(date('Y/m/d', $start_time), $new_holidays);
$is_workingdays = in_array(date('Y/m/d', $start_time), $new_workingdays); if ($is_holidays || $is_workingdays) {
$workingdays[] = date('Y/m/d', $start_time);
}
} return $workingdays;
} # 新增工作日
protected function new_workingdays()
{
$days = [
'2020/05/09',
]; return $days;
} # 新增休息日
protected function new_holidays()
{
$days = [
'2020/05/01',
'2020/05/04',
'2020/05/05',
]; return $days;
} }
$start_time = strtotime('2020-05-06 10:00:00');
$over_time = strtotime('2020-05-11 18:00:00'); $work = new WorkTime();
$working_hours = $work->get_working_hours($start_time, $over_time); var_dump($working_hours);

php计算两个时间段内的 工作日 工作小时的更多相关文章

  1. PHP计算两个时间段是否有交集(边界重叠不算)

    优化前的版本: /** * PHP计算两个时间段是否有交集(边界重叠不算) * * @param string $beginTime1 开始时间1 * @param string $endTime1 ...

  2. 用VBA计算两个日期之间的工作日(去掉周末两天)

    最近公司HR和Finance想算员工的工作天数,想让我帮忙写些VBA,自己从网上找了下代码,自己再改改,以下来自网络. 计算两个日期之间的工作日,用VBA,因量大,最好用数组做 Sub kk() Di ...

  3. C 语言实例 - 计算两个时间段的差值

    C 语言实例 - 计算两个时间段的差值 C 语言实例 C 语言实例 计算两个时间段的差值. 实例 #include <stdio.h> struct TIME { int seconds; ...

  4. Oracle 查询两个时间段内的所有日期列表

    1.查询某时间段内日期列表 select level,to_char(to_date('2013-12-31','yyyy-mm-dd')+level-1,'yyyy-mm-dd') as date_ ...

  5. sql server两个时间段内,求出周末的量

    公司有个表记录了出差(加班)的初始时间和截止时间,现在要计算出加班时间,之前的设计并没有考虑到这部分,因此本人通过sql重新计算周末数 表formmain starttime endtime 使用游标 ...

  6. mysql 计算两个日期之间的工作日天数

    创建透视表t500 建表 CREATE TABLE `t500` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE ...

  7. SQL计算两个时间段相隔时间

    SQL语句: select cast(floor(datediff(minute,时间1,时间2) / 1440) as varchar)+'天'+ cast(floor((datediff(minu ...

  8. java计算两个时间相差(天、小时、分钟、秒)

    public static Long dateDiff(String startTime, String endTime, String format, String str) { // 按照传入的格 ...

  9. 计算一段日期内的周末天数的php代码(星期六,星期日总和)

    代码如下: /*| Author: Yang Yu <niceses@gmail.com>| @param char|int $start_date 一个有效的日期格式,例如:200910 ...

随机推荐

  1. parrot os安装drozer

    dz需要支持 大部分parrot都装好了,只有Protobuf未安装 apt install Protobuf 安装dz 下面下载https://labs.f-secure.com/tools/dro ...

  2. Rocket - debug - TLDebugModuleInner - DMI Register Control and Status

    https://mp.weixin.qq.com/s/tI41wu0xaIQ5PRq6F82tNw 简单介绍TLDebugModuleInner中生成DMI控制和状态寄存器使用到的状态. 1. abs ...

  3. 【Flume】知识总结

    Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据:同时,Flume提供对数据进行简单处理,并 ...

  4. lambda操作DataTable进阶版

    using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Text; ...

  5. .NET开发者省份分布排名

    什么叫.NET开发者省份分布排名呢? 顾名思义,这几个词大家都认识,.NET开发者都集中在城市,涵盖一线城市到五线城市.排名的方法非常简单粗暴,就是根据本公众号(dotnet跨平台)的省份订阅读者数量 ...

  6. ASP.NET Core 3.1 WebApi部署到腾讯云CentOS 7+Docker

    一.准备 首先需要有一台CentOS服务器,安装最新版Docker,配置镜像加速等,安装方法网上很多,下面是一些相关指令: yum install -y yum-utils device-mapper ...

  7. Flink 如何分流数据

    场景 分流方式 如何分流 使用Filter分流 使用Split分流 使用Side Output分流 场景 获取流数据的时候,通常需要根据所需把流拆分出其他多个流,根据不同的流再去作相应的处理. 举个例 ...

  8. qt-embedded-4.5.3移植到FL2440开发板

    1. 2.configure配置 ./configure -opensource -confirm-license -release -shared -fast -no-qt3support -no- ...

  9. App接口设计之token的php实现

    为了保证移动端和服务端数据传输相对安全,需要对接口进行加密传输. 一.ttoken的设计目的:  因为APP端没有和PC端一样的session机制,所以无法判断用户是否登陆,以及无法保持用户状态,所以 ...

  10. @loj - 2106@ 「JLOI2015」有意义的字符串

    目录 @description@ @solution@ @accepted code@ @details@ @description@ B 君有两个好朋友,他们叫宁宁和冉冉.有一天,冉冉遇到了一个有趣 ...