PHP显示工资单日期

PHP显示工资单日期,php,mysql,Php,Mysql,我有一个页面,需要显示滚动工资类型日期。该工资单的发放时间为1月15日和16月底。我有一个显示当前工资单的页面,其中有一个向前或向后的按钮。我有以下代码,大部分时间都有效,但偶尔会跳过付款期。有更好的方法吗 //find out what the offset is for the pay period we want to see $offset = $_GET['offset']; $offsetdays = $offset * 15; //Find out what day it is

我有一个页面,需要显示滚动工资类型日期。该工资单的发放时间为1月15日和16月底。我有一个显示当前工资单的页面,其中有一个向前或向后的按钮。我有以下代码,大部分时间都有效,但偶尔会跳过付款期。有更好的方法吗

//find out what the offset is for the pay period we want to see
$offset = $_GET['offset'];
$offsetdays = $offset * 15;

//Find out what day it is 
$dayofmonth = date('j', mktime( 0, 0, 0,date("m"), -$offsetdays, date("Y")));

//if it is the second half of the month set the pay period to be the 1-15th of this month
if($dayofmonth <= 15){
//Echo display dates in HTML
Echo "<div style='width:15%; float:right; text-align:center'>Pay Period End Date <BR>";
echo date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -$offsetdays, date("2014"))), 15, date("2014"))); //End Date
Echo "</div> <div style='width:1%; float:right; text-align:center'>|<BR>|</div>";
Echo "<div style='width:15%; float:right; text-align:center'>Pay Period Start Date <BR>";
Echo date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -$offsetdays,     date("2014"))), 1, date("2014"))); //Start Date
Echo "</div>";
Echo "<BR>";

//Set variable dates for SQL
$checkoffset = offsetdays - 15;
$payrollstartdate = date("Y-m-d", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -                $offsetdays, date("2014"))), 1, date("Y")));
$payrollenddate = date("Y-m-d", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -    $offsetdays, date("2014"))), 15, date("Y")));
$checkdayte = date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -    $checkoffset, date("2014")))+1, 0, date("Y")));
}


//if it is the first half of the month set the pay period to be the 16- end of this month
if($dayofmonth > 15){
//Echo display dates in HTML
Echo "<div style='width:15%; float:right; text-align:center'>Pay Period End Date <BR>";
echo date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -$offsetdays, date("2014")))+1, 0, date("2014"))); //End Date
Echo "</div> <div style='width:1%; float:right; text-align:center'>|<BR>|</div>";
Echo "<div style='width:15%; float:right; text-align:center'>Pay Period Start Date <BR>";
echo date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -$offsetdays, date("2014"))), 16, date("2014"))); //Start Date
Echo "</div>";
Echo "<BR>";

//Set variable dates for SQL
$checkoffset = offsetdays - 15;

$payrollstartdate = date("Y-m-d", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -    $offsetdays, date("2014"))), 16, date("2014")));
$payrollenddate = date("Y-m-d", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -    $offsetdays, date("2014")))+1, 0, date("2014")));
$checkdayte = date("m/d/Y", mktime(0, 0, 0, date("m", mktime( 0, 0, 0,date("m"), -$checkoffset, date("2014"))), 15, date("2014")));
}
//找出我们希望看到的付款期的偏移量
$offset=$_GET['offset'];
$offsetdays=$offset*15;
//看看今天是什么日子
$dayofmonth=日期('j',mktime(0,0,0,日期(“m”),-$offsetdays,日期(“Y”);
//如果是下半月,则将支付期设置为本月1-15日
如果($dayofmonth 15){
//以HTML格式显示日期
回显“付款期结束日期
”; 回音日期(“m/d/Y”)、mktime(0,0,0,日期(“m”)、mktime(0,0,0,日期(“m”)、-$offsetdays,日期(“2014”)+1,0,日期(“2014”);//结束日期 回声“|
|”; 回显“付款期开始日期
”; 回音日期(“m/d/Y”)、mktime(0,0,0,日期(“m”)、mktime(0,0,0,日期(“m”)、-$offsetdays,日期(“2014”)、16,日期(“2014”);//开始日期 回声“; 回声“
”; //为SQL设置可变日期 $checkoffset=抵销天数-15; $payrollstartdate=日期(“Y-m-d”)、mktime(0,0,0,日期(“m”)、mktime(0,0,0,日期(“m”)、-$offsetdays,日期(“2014”)、16,日期(“2014”); $payrollenddate=日期(“Y-m-d”)、mktime(0,0,0,日期(“m”)、mktime(0,0,0,日期(“m”)、-$offsetdays,日期(“2014”)+1,0,日期(“2014”); $checkdayte=日期(“m/d/Y”)、mktime(0,0,0,日期(“m”)、mktime(0,0,0,日期(“m”)、-$checkoffset,日期(“2014”)、15,日期(“2014”); }
将偏移量增加1将显示下一个付款期,将其减少1将显示最后一个付款期

我也尝试在MySQL中这样做,但运气不太好

更详细地说,这里是我希望发生的事情:

今天(2/27),当我进入页面时,我需要开始日期为2014年2月15日,结束日期为2014年2月28日。当我增加抵销变量时,我需要开始日期为2014年3月1日,结束日期为2014年3月15日


下周二(3/4),当我进入本页时,我需要开始日期为2014年3月1日,结束日期为2014年2月15日。当我增加抵销变量时,我需要开始日期为2014年3月15日,结束日期为2014年3月31日。

可能导致跳过期间的原因之一是您的计算方法
$offsetdays
。所有的月份都不是30天长,所以将周期偏移量乘以15并不总是有效的,尤其是对于大偏移量

<?php
// Set default timezone to avoid warnings
date_default_timezone_set("UTC");

function get_period_bounds($offset = 0) {
    $secondhalf  = ($offset % 2) == 0 xor (int) date('j') >= 15;
    $monthnumber = ceil((int) date('n') + $offset / 2);;

    $period_begin = mktime(0, 0, 0, // 00:00:00
                           $monthnumber,
                           $secondhalf ? 16 : 1);
    $period_end   = mktime(0, 0, 0, // 00:00:00
                           $secondhalf ? $monthnumber + 1 : $monthnumber,
                           $secondhalf ? 0 : 15);

    return array($period_begin, $period_end);
}
月 现在我们知道了目标期在哪个半月,我们需要知道目标期在哪个月。由于一个月内正好有两个期间,因此有一半的抵销是月份抵销。因此,我们将偏移量的一半添加到当前月份,并
ceil
结果。大多数神奇之处都发生在
mktime
函数中,该函数可以理解,例如,0是上一年的最后一个月

开始日期 开始日期非常简单:我们只需使用当前年份的相对月数(默认情况下在
mktime
中使用)。如果目标时段为第一个时段,则时段的第一天为第一天,否则为第十六天

为了可读性,我使用了三元运算符:

(BOOLEAN TEST) ? VALUE_IF_TRUE : VALUE_IF_FALSE
结束日期 上半年的情况很简单,我们使用相对月指数,结束日是15日。对于下半年,最后一个小技巧是获取当月最后一天的数字。为此,我们(再次)依靠
mktime
的能力,通过在月数上加一并将日数设置为0(即前一个月的最后一天),转换相对秒/分钟/小时/天/月/年。综上所述,我们得到的是周期月份后一个月之前的一个月的最后一天,即周期月份的最后一天

检查 您可能需要检查此公式是否偶尔跳过一段时间。这个小循环将帮助您做到这一点:

<?php

$len = 500; // Change to your needs
$last = 0;
for ($i = -$len; $i <= $len; $i++) {
    $a = get_period_bounds($i);
    printf("Period %d is from %s to %s [%s]<br />",
           $i, // Period number
           date('Y-m-d', $a[0]), // Begin date
           date('Y-m-d', $a[1]), // End date
           $last + 3600 * 24 == $a[0] ? 'x' : ' ' // Prints a x if the last day of the previous period is the day before the first day of this period
    );
    $last = $a[1];
}

可能导致跳过周期的原因之一是您的计算方法
$offsetdays
。所有的月份都不是30天长,所以将周期偏移量乘以15并不总是有效的,尤其是对于大偏移量

<?php
// Set default timezone to avoid warnings
date_default_timezone_set("UTC");

function get_period_bounds($offset = 0) {
    $secondhalf  = ($offset % 2) == 0 xor (int) date('j') >= 15;
    $monthnumber = ceil((int) date('n') + $offset / 2);;

    $period_begin = mktime(0, 0, 0, // 00:00:00
                           $monthnumber,
                           $secondhalf ? 16 : 1);
    $period_end   = mktime(0, 0, 0, // 00:00:00
                           $secondhalf ? $monthnumber + 1 : $monthnumber,
                           $secondhalf ? 0 : 15);

    return array($period_begin, $period_end);
}
月 现在我们知道了目标期在哪个半月,我们需要知道目标期在哪个月。由于一个月内正好有两个期间,因此有一半的抵销是月份抵销。因此,我们将偏移量的一半添加到当前月份,并
ceil
结果。大多数神奇之处都发生在
mktime
函数中,该函数可以理解,例如,0是上一年的最后一个月

开始日期 开始日期非常简单:我们只需使用当前年份的相对月数(默认情况下在
mktime
中使用)。如果目标时段为第一个时段,则时段的第一天为第一天,否则为第十六天

为了可读性,我使用了三元运算符:

(BOOLEAN TEST) ? VALUE_IF_TRUE : VALUE_IF_FALSE
结束日期 上半年的情况很简单,我们使用相对月指数,结束日是15日。对于下半年,最后一个小技巧是获取当月最后一天的数字。为此,我们(再次)依靠
mktime
的能力,通过在月数上加一并将日数设置为0(即前一个月的最后一天),转换相对秒/分钟/小时/天/月/年。综上所述,我们得到的是周期月份后一个月之前的一个月的最后一天,即周期月份的最后一天

检查 您可能需要检查此公式是否偶尔跳过一段时间。这个小循环将帮助您做到这一点:

<?php

$len = 500; // Change to your needs
$last = 0;
for ($i = -$len; $i <= $len; $i++) {
    $a = get_period_bounds($i);
    printf("Period %d is from %s to %s [%s]<br />",
           $i, // Period number
           date('Y-m-d', $a[0]), // Begin date
           date('Y-m-d', $a[1]), // End date
           $last + 3600 * 24 == $a[0] ? 'x' : ' ' // Prints a x if the last day of the previous period is the day before the first day of this period
    );
    $last = $a[1];
}

可能导致跳过周期的原因之一是您的计算方法
$offsetdays
。所有的月份都不是30天长,所以将周期偏移量乘以15并不总是有效的,尤其是对于大偏移量

<?php
// Set default timezone to avoid warnings
date_default_timezone_set("UTC");

function get_period_bounds($offset = 0) {
    $secondhalf  = ($offset % 2) == 0 xor (int) date('j') >= 15;
    $monthnumber = ceil((int) date('n') + $offset / 2);;

    $period_begin = mktime(0, 0, 0, // 00:00:00
                           $monthnumber,
                           $secondhalf ? 16 : 1);
    $period_end   = mktime(0, 0, 0, // 00:00:00
                           $secondhalf ? $monthnumber + 1 : $monthnumber,
                           $secondhalf ? 0 : 15);

    return array($period_begin, $period_end);
}
月 现在我们知道了目标期在哪个半月,w
BIMONTHLY_PAY_PERIOD_ADD('1941-12-01', -1) goes back one period to '1941-11-16'
BIMONTHLY_PAY_PERIOD_ADD('2014-03-16', 3) goes forward three to '2014-05-01'
DELIMITER $$
DROP FUNCTION IF EXISTS `BIMONTHLY_PAY_PERIOD_ADD`$$

CREATE FUNCTION `BIMONTHLY_PAY_PERIOD_ADD`(datestamp DATETIME, incr INT) 
    RETURNS DATE
    NO SQL
    DETERMINISTIC
    COMMENT 'returns first day of a pay period in the future or past'
BEGIN
    DECLARE pp DATE;
    SET pp = BIMONTHLY_PAY_PERIOD_START(datestamp);
    IF ABS(incr) MOD 2 = 1
    THEN 
       SET pp = pp + INTERVAL 16 DAY;
       SET incr = incr - 1;
    END IF;
    SET incr = incr DIV 2;
    SET pp = pp + INTERVAL incr MONTH;
    RETURN BIMONTHLY_PAY_PERIOD_START(pp);
    END$$

DELIMITER ;
employee_id  INT          identifies the employee
clock_in   DATETIME       the date and time the employee clocked in
clock_out  DATETIME       the date and time the employee clocked out
SELECT employee_id, 
       BIMONTHLY_PAY_PERIOD_START(clock_out) AS pay_period,
       SUM(TIMESTAMPDIFF(MINUTE,clock_in, clock_out)) AS minutes_worked
  FROM payroll_data
 WHERE clock_out >= BIMONTHLY_PAY_PERIOD_ADD(NOW(), -6)
   AND clock_out < BIMONTLY_PAY_PERIOD_START(NOW())
 GROUP BY employee_id, BIMONTHLY_PAY_PERIOD_START(clock_out) 
 ORDER BY employee_id, BIMONTHLY_PAY_PERIOD_START(clock_out)
BIMONTHLY_PAY_PERIOD_ADD(NOW(),1) - INTERVAL 1 DAY