如何在特定时间段内显示 php 中的任何内容?

How to display anything in php in between particular time duration?

我有一个如下所示的 php 代码,我想在其中显示一周中两个日历日之间的任何内容。

$data->{"select_start_day"}; $data->{"start_time"}; $data->{"select_end_day"};$data->{"end_time"}; 中的值由用户控制。

PHP代码:

    if (file_exists('feeds/ptp-ess_landing.json')) {
    $data = json_decode(file_get_contents('feeds/ptp-ess_landing.json'));
    }

    date_default_timezone_set('America/Toronto');
    $arradate = strtolower(date('D'));
    $nowtime = (int)date('His');


    $start_day=$data->{"select_start_day"};
    $start_time=$data->{"start_time"};

    $end_day=$data->{"select_end_day"};
    $end_time=$data->{"end_time"};

例如,假设用户输入$start_daysun $start_time 作为 143400 $end_day 作为 wed $end_time 作为 140000

以上持续时间意味着我们在范围内,它应该显示我们想要显示的任何内容,直到明天下午 2 点,因为明天是星期三。我在美国东部时间。

我正在使用以下代码提取星期几和时间:

date_default_timezone_set('America/Toronto');
$arradate = strtolower(date('D'));
$nowtime = (int)date('His');

问题陈述:

我想知道我是否需要使用逻辑来打印任何内容 Sunday 143400Wednesday 140000.

if()    {
    echo "Its in range";
}

案例:

  1. 如果应该从周一上午 8 点周一下午 6 点应用覆盖并且今天是星期三 那么覆盖不适用。

  2. 如果是 星期一下午 6 点星期五下午 6 点,那么覆盖将适用于 周一 6 小时周二全天周三全天周四全天, 周五下午 6 点前

  3. 如果 星期天下午 6 点星期一下午 6 点,那么覆盖将工作 6 小时星期一星期一18 小时。

  4. 如果星期二下午 6 点星期五下午 6 点并且今天是星期二晚上 9 点 那么覆盖将适用。

  5. 如果它是 星期四下午 6 点星期三下午 6 点,那么覆盖将工作 6 小时星期四星期五 24 小时星期六 24 小时星期日 24 小时周一 24 小时周二 24 小时周三 24 小时星期四 18 小时

我会以相同的格式保留所有日期。 Unix 时间是存储时间的好方法,因为您可以轻松 运行 计算。

在您的示例中,您同时使用字符串和数字进行计算。事实上,您有 3 种不同的方式来表示日期。我建议仅使用 date() 来保存和比较所有值,并且在向最终用户显示时仅格式化 Unix 时间戳。

↓↓↓↓ 新编辑↓↓↓

仔细看看你的代码是什么returning:

$arradate = strtolower(date('D')); //echos the day ex: sun
$nowtime = (int)date('His'); //echos a different format ex: 25019

并仔细阅读 date 函数的文档,特别是您现在选择的参数 'His' 将 return:

H 24 小时制小时格式,前导零从 00 到 23

i 分钟,前导零 00 到 59

s 带前导零的秒数 00 到 59

现在考虑 date() return 是一个 Unix 时间戳,您将看到失败。您只需要删除所有代码中的日期格式,保存显示给最终用户的元素。计算机知道今天是星期三没有任何好处。电脑只从1970年开始统计

所以你只需要一个参数来调用当前日期。两者都有效:

$arradate = date(); 
$nowtime = date(); 

最后,在阅读了有关 Unix 时间的内容后,您会发现存储的日期是倒过来的。你 end_time 是第 0 天,你的开始时间是在那之后的两天。

试试这个:

$dowMap = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

$arradate = date('D');

$arradateNum = array_search($arradate, $dowMap);

$start_dayNum = array_search($start_day, $dowMap);

$end_dayNum = array_search($end_day, $dowMap);

if(
    ($arradateNum >= $start_dayNum && $nowtime>=$data->{"start_time"}) && 
    ($arradateNum <= $end_dayNum && $nowtime <= $data->{"end_time"})
) {
    echo "Show Anything";  
}

您应该通读 PHP 手册并了解如何创建 DateTime 对象和各种可用的日期格式。

首先,您需要将用户输入转换为 DateTimeObjects。由于用户输入仅包含 Day(用 D 表示)和 Time(用 His 表示),您可以使用以下代码获取这些对象。

date_default_timezone_set('America/Toronto'); //Setting the Timezone
//These are the User Inputs
$start_day = 'tue';
$start_time  = 181300;

$end_day = 'fri';
$end_time  = 134500;
//User Input Ends

//Create the Date Time Object for Start and End Date
$startDate = DateTime::createFromFormat ( 'D His', $start_day . ' '. $start_time);
$endDate = DateTime::createFromFormat ( 'D His', $end_day . ' '. $end_time);

您可以在 Manual

中检查可用于 createFromFormat 的各种选项

现在您有了日期时间对象,您可以从中获取任何值。让我们为开始日期和结束日期获取数字格式的星期几以及数字格式的小时。

$startHour = $startDate->format('G');  //24-hour format of an hour without leading zeros
$startDay = $startDate->format('N');  //numeric representation of the day of the week

$endHour = $endDate->format('G'); //24-hour format of an hour without leading zeros
$endDay = $endDate->format('N');  //numeric representation of the day of the week

您可以查看 GN 格式以及 Manual

中可用的其他选项

我们需要检查时间是周二下午 6 点到周五下午 6 点之间。

首先我们会检查日期是否在星期二和星期五之间。我们有上面的 $startDay$endDay 变量来确定。 星期二对应的数值是2,星期五对应的数值是5。

对于时间范围,我们有 $startHour$endHour 变量。格式中的 6PM 表示为 18 ( 12 + 6).

因此我们可以使用以下代码检查此条件:

if ( $startDay >= 2 && $endDay <= 5 && $startHour >= 18 and $endHour <= 18 ) {
    echo 'In Range';
} else {
    echo 'out of Range';
}

这样您就可以检查任何复杂的条件。您可以在 3v4l

查看在线演示

这是我的尝试,使用映射 table 和字符串连接。如果日期顺序相反,则不起作用。例如如果今天是星期天,select_start_day的值为Friselect_end_day的值为Mon,那么就不行了。

<?php

$arr = (object) [
    'select_start_day' => 'wed',
    'start_time' => 143400,
    'select_end_day' => 'wed',
    'end_time' => 220000
];

$map_daysToNumbers = ['sun'=>1, 'mon'=>2, 'tue'=>3, 'wed'=>4, 'thu'=>5, 'fri'=>6, 'sat'=>7];

$startString = $map_daysToNumbers[$arr->select_start_day] . str_pad($arr->start_time, 6, '0', STR_PAD_LEFT);
$endString = $map_daysToNumbers[$arr->select_end_day] . str_pad($arr->end_time, 6, '0', STR_PAD_LEFT);

$tz = new \DateTimeZone('America/Toronto');

$today = new \DateTime('now', $tz);

$todayString = ($today->format('w')+1) . $today->format('His');

if($startString <= $todayString && $todayString <= $endString){
    echo 'In range';
}

或基于日期的解决方案。它们都不能保证满足您的需求。

$arr = (object) [
    'select_start_day' => 'tue',
    'start_time' => 143400,
    'select_end_day' => 'wed',
    'end_time' => 220000
];

$tz = new \DateTimeZone('America/Toronto');

// extrapolate the start date looking 7 days back
$sDate = new \DateTime('tomorrow midnight', $tz);
$sDate->modify('last '.$arr->select_start_day);
$sDate->setTime(...str_split(str_pad($arr->start_time, 6, '0', STR_PAD_LEFT), 2));
// or bound the start date to be between last sunday and next saturday
$sDate = new \DateTime('Saturday last week', $tz);
$sDate->modify('next '.$arr->select_start_day);
$sDate->setTime(...str_split(str_pad($arr->start_time, 6, '0', STR_PAD_LEFT), 2));

// extrapolate the end date
$eDate =  clone $sDate;
$eDate->modify('yesterday'); // workaround to consider the same day possibility
$eDate->modify('next '.$arr->select_end_day);
$eDate->setTime(...str_split(str_pad($arr->end_time, 6, '0', STR_PAD_LEFT), 2));

// Test against today
$today = new \DateTime('now', $tz);

var_dump($sDate);
var_dump($eDate);
var_dump($today);

if($sDate <= $today && $today <= $eDate){
    echo 'In range';
}

第一种方式总是从过去开始,根据您的范围,它可能包括今天也可能不包括。第二个将始终绑定到当前周,我相信这就是您想要的。

正如@mickmackusa 和我在评论中所说,给你的要求是模糊和不精确的。您要么需要更严格的规则,要么需要基于日期的解决方案,即给定两个精确的日期(时间戳),然后比较日期是否介于它们之间。这是我在第二个选项中尝试做的,但不知道日期应该是过去还是将来。

这个问题的难点在于处理周末附近 'wrap' 的范围,即您的示例案例 5

我建议设置一个涵盖两周的天数参考数组

$days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
$days = array_merge($days, $days);

对其进行切片,使其从起始点的那一天开始(将从 0 重新索引)

$days = array_slice($days, array_search($startDay, $days));

然后您可以为现在和终点建立一个参考整数

$nowRef = (int) (array_search($nowDay, $days) . $nowTime);
$endRef = (int) (array_search($endDay, $days) . $endTime);

请注意,您可以对起点执行相同的操作,但由于天数数组以 $startDay(索引 0)开头,这相当于 $startTime

你的 if 条件就变成了

if ($nowRef >= $startTime && $nowRef <= $endRef) {
   // IN RANGE
}

N.B. 这假设您的用户输入已经过验证,并且如果开始日期和结束日期相同则结束时间大于开始时间


您的命名约定有点不一致,所以我重命名了您的一些变量并切换为驼峰式大小写以提高可读性

$nowDay = $arradate;
$nowTime = $nowtime;

$startDay = $start_day;
$startTime = $start_time;

$endDay = $end_day;
$endTime = $end_time;

首先,我可以推荐你使用面向对象的编程来更好地结构化你的代码和分解任务。您可以创建一个抽象来处理工作日时间。例如:

class WeekDayTime
{
    /** @var string[] map of the name of days and their number */
    const DAY_MAP = [
        'Mon' => 1,
        'Tue' => 2,
        'Wed' => 3,
        'Thu' => 4,
        'Fri' => 5,
        'Sat' => 6,
        'Sun' => 7
    ];

    /** @var int number of the day */
    private $dayNumber;

    /** @var int amount of hours */
    private $hours;

    /** @var int amount of minutes */
    private $minutes;

    /** @var int amount of seconds */
    private $seconds;

    /**
     * Constuctor
     * @param string $day number of the day
     * @param int $hours amount of hours
     * @param int $minutes amount of minutes
     * @param int $seconds amount of seconds
     */ 
    public function __construct(string $day, int $hours, int $minutes, int $seconds)
    {
        assert(array_key_exists($day, static::DAY_MAP), 'The day is incorrect');
        assert($hours < 24, 'The hours must be less than 24');
        assert($minutes < 60, 'The hours must be less than 60');
        assert($seconds < 60, 'The hours must be less than 60');
        $this->dayNumber = static::DAY_MAP[$day];
        $this->hours = $hours;
        $this->minutes = $minutes;
        $this->seconds = $seconds;
    }

    /**
     * Get number of the day
     * @return int number of the day
     */
    public function getDayNumber(): int
    {
        return $this->dayNumber;
    }

    /**
     * Get amount of hours
     * @return int amount of hours
     */
    public function getHours(): int
    {
        return $this->hours;
    }

    /**
     * Get amount of minutes
     * @return int amount of minutes
     */
    public function getMinutes(): int
    {
        return $this->minutes;
    }

     /**
     * Get amount of seconds
     * @return int amount of seconds
     */
    public function getSeconds(): int
    {
        return $this->seconds;
    }

    /**
     * Check if the current week day time is less the a denined week day time
     * @param WeekDayTime $value value which will be compared
     * @return bool status of the checking
     */
    public function isLessOrEqual(WeekDayTime $value): bool
    {
        $isLess = $this->dayNumber < $value->dayNumber;
        $isLessOrEqual = $this->dayNumber === $value->getDayNumber()
            && $this->hours <= $value->getHours()
            && $this->minutes <= $value->getMinutes()
            && $this->seconds <= $value->getSeconds();
        return $isLess || $isLessOrEqual;
    }

    /**
     * Check if the current week day time is greater the a denined week day time
     * @param WeekDayTime $value value which will be compared
     * @return bool status of the checking
     */
    public function isGreaterOrEqual(WeekDayTime $value): bool
    {
        $isGreater = $this->dayNumber > $value->dayNumber;
        $isGreaterOrEqual = $this->dayNumber === $value->getDayNumber()
            && $this->hours >= $value->getHours()
            && $this->minutes >= $value->getMinutes()
            && $this->seconds >= $value->getSeconds();
        return $isGreater || $isGreaterOrEqual;
    }
}

这将是对象值,其中包含有关星期几和时间的信息以及比较此 class 对象的方法。在它之后,您可以创建一个 class 来包含一个工作日时间范围。例如:

class WeekDayTimeRange
{
    /** WeekDayTime range start */
    private $start;

    /** WeekDayTime range end */
    private $end;

    /**
     * Constuctor
     * @param WeekDayTime $start range start
     * @param WeekDayTime $end range end
     */
    public function __construct(WeekDayTime $start, WeekDayTime $end)
    {
        $this->start = $start;
        $this->end = $end;
    }

    /**
     * Check if a date-time occurs into the range
     * @param DateTimeInterface the date-time which will be checked
     * @return bool status of the checking
     */
    public function inRange(DateTimeInterface $dateTime): bool
    {}
}

如您所见,class 包含有关范围开始、范围结束和检查范围内任何日期时间出现的方法的信息。如果您想检查开始值小于结束值的范围(例如从星期一到星期五),您可以执行以下 inRange 方法的实现:

public function inRange(DateTimeInterface $dateTime): bool
{
    $day = $dateTime->format('D');
    $hours = $dateTime->format('H');
    $minutes = $dateTime->format('i');
    $seconds = $dateTime->format('s');
    $weekDayTime = new WeekDayTime($day, $hours, $minutes, $seconds);

    return $this->start->isLessOrEqual($weekDayTime) && $this->end->isGreaterOrEqual($weekDayTime);
}

但是如果你想检查起始值大于结束值的范围(例如从星期五到星期一),你应该将范围分为两个范围:从范围开始到周末和从一周开始到范围结束并检查日期时间在两个范围内的出现。例如:

public function inRange(DateTimeInterface $dateTime): bool
{
    $day = $dateTime->format('D');
    $hours = $dateTime->format('H');
    $minutes = $dateTime->format('i');
    $seconds = $dateTime->format('s');
    $weekDayTime = new WeekDayTime($day, $hours, $minutes, $seconds);

    // if the range end is less then range start we break the current range to two range
    if ($this->end->isLessOrEqual($this->start))  {
        $range1 = new WeekDayTimeRange($this->start, new WeekDayTime('Sun', 23,59,59));
        $range2 = new WeekDayTimeRange(new WeekDayTime('Mon', 0,0,0), $this->end);
        return $range1->inRange($dateTime) || $range2->inRange($dateTime);
    }

    return $this->start->isLessOrEqual($weekDayTime) && $this->end->isGreaterOrEqual($weekDayTime);
}

使用示例:

// Date occurs into the range from Tuesday to Friday
$start = new WeekDayTime('Tue', 10, 0,0);
$end = new WeekDayTime('Fri', 14, 0,0);
$range = new WeekDayTimeRange($start, $end);
$range->inRange(DateTime::createFromFormat('Y-m-d H:i:s', '2019-10-03 10:00:00'));

// Date doesn't occur into the range from Tuesday to Friday
$start = new WeekDayTime('Tue', 10, 0,0);
$end = new WeekDayTime('Fri', 14, 0,0);
$range = new WeekDayTimeRange($start, $end);
$range->inRange(DateTime::createFromFormat('Y-m-d H:i:s', '2019-10-05 10:00:00'));

// Date doesn't occur into the range from Friday to Tuesday
$start = new WeekDayTime('Fri', 14, 0,0);
$end = new WeekDayTime('Tue', 10, 0,0);
$range = new WeekDayTimeRange($start, $end);
$range->inRange(DateTime::createFromFormat('Y-m-d H:i:s', '2019-10-03 10:00:00'));

// Date occurs into the range from Friday to Tuesday
$start = new WeekDayTime('Fri', 14, 0,0);
$end = new WeekDayTime('Tue', 10, 0,0);
$range->inRange(DateTime::createFromFormat('Y-m-d H:i:s', '2019-10-05 10:00:00'));

您可以在 sandbox

查看演示

这是显示持续时间之间任何内容的示例

在开始时间和结束时间中添加多伦多的任何时间..您将在每周的这一天和持续时间之间得到输出。

date_default_timezone_set('America/Toronto');
$now     = new DateTime(); 
$date    = $now->format('Y-m-d');
$time    = $now->format('h:i A');
$dayname = strtolower(date('l', strtotime($date))); //it will give you today's day name


$start_day = "monday"; //lets consider your data will be come as startday="monday" from $data->{"select_start_day"};
$start_time = '07:50 AM'; //lets consider your data will be come as starttime="07:50 AM" from $data->{"start_time"}; 
$end_day = "tuesday"; //lets consider your data will be come as endday="monday" from $data->{"select_end_day"};
$end_time = '08:26 AM'; //lets consider your data will be come as endtime="08:26 AM" from $data->{"end_time"}; 

$todays_date_time    = strtotime($dayname);
$start_day_time      = strtotime($start_day);
$end_day_time        = strtotime($end_day);
$timeconvert         = strtotime($time);
$timeconvertstart    = strtotime($start_time);
$timeconvertend      = strtotime($end_time);

if($todays_date_time >= $start_day_time && $todays_date_time <= $end_day_time ) 
 {
  if ($timeconvert >= $timeconvertstart && $timeconvert <= $timeconvertend) { 
     echo "test";
 }
}

希望本文对您有所帮助!