【问题标题】:In PHP, check if time is between sunset and sunrise在 PHP 中,检查时间是否在日落和日出之间
【发布时间】:2020-09-23 09:55:28
【问题描述】:

我已经在 SO 上讨论了多个问题和答案,但我似乎无法弄清楚。我实际上是在尝试检查某个时间某个地点(纬度/经度)是否是夜晚。

到目前为止,我设法获得了特定位置的日出和日落时间,然后我试图将其与当前时间进行比较。我有一点灰姑娘的情况,它可以正常工作到午夜来袭。

我正在创建我的变量进行比较,如下所示:


    $currenttime = DateTime::createFromFormat('Y-m-d H:i', $templooptime);
    $sunsettime = DateTime::createFromFormat('Y-m-d H:i', $sunsetfinal);
    $sunrisetime = DateTime::createFromFormat('Y-m-d H:i', $sunrisefinal);

我正在做这样一个简单的 IF 语句:

    if ($currenttime>$sunsettime) {
       $nightminutes++;
    }

这会输出以下内容:

Current Time:2020-09-22 23:58:00| Location: 50.1776906598,-51.077228098126 | Sunset Start: 2020-09-22 18:48:00 |Sunrise Start: 2020-09-22 06:45:00 | Night:287
Current Time:2020-09-22 23:59:00| Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 |Sunrise Start: 2020-09-22 06:44:00 | Night:288
Current Time:2020-09-23 00:00:00| Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 |Sunrise Start: 2020-09-23 06:46:00 | Night:0
Current Time:2020-09-23 00:01:00| Location: 50.25067682914,-50.798287405434 | Sunset Start: 2020-09-23 18:44:00 |Sunrise Start: 2020-09-23 06:45:00 | Night:0

当我将逻辑更改为:

if ($currenttime>$sunsettime && $currenttime<$sunrisetime) {
    $nightminutes++;
}

它输出:

Current Time:2020-09-22 23:58:00| Location: 50.1776906598,-51.077228098126 | Sunset Start: 2020-09-22 18:48:00 |Sunrise Start: 2020-09-22 06:45:00 | Night:0
Current Time:2020-09-22 23:59:00| Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 |Sunrise Start: 2020-09-22 06:44:00 | Night:0
Current Time:2020-09-23 00:00:00| Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 |Sunrise Start: 2020-09-23 06:46:00 | Night:0
Current Time:2020-09-23 00:01:00| Location: 50.25067682914,-50.798287405434 | Sunset Start: 2020-09-23 18:44:00 |Sunrise Start: 2020-09-23 06:45:00 | Night:0

我该如何解决这个问题?

更新根据 RO 的回答将日落时间设置为提前一天,仍然存在这个问题:

Current Time:2020-09-22 23:59:00 | Location: 50.202093865458,-50.984342445684 | Sunset Start: 2020-09-22 18:47:00 | Sunrise Start: 2020-09-23 06:46:00 | Night:288
Current Time:2020-09-23 00:00:00 | Location: 50.226422634856,-50.891362177619 | Sunset Start: 2020-09-23 18:45:00 | Sunrise Start: 2020-09-24 06:47:00 | Night:0

当它超过午夜时,日落时间比当前时间少,因此它显示为 false。有什么想法吗?

UPDATE 2这是我正在使用的基本代码(摘录):

<?php
    $fulltimestampdateforloop = new DateTime('2020-09-22 23:58:00');
    $coords=["50.1776906598,-51.077228098126","50.202093865458,-50.984342445684","50.226422634856,-50.891362177619","50.25067682914,-50.798287405434"];
    $nightmin=0;
    $offset2=2;
    foreach ($coords as $value) {   
        $latlng = explode(",", $value);
        $lat = $latlng[0];
        $lng = $latlng[1];  
        $str_timestamp = $fulltimestampdateforloop->format('Y-m-d');
        $str_flighttime =$fulltimestampdateforloop->getTimestamp();
        
        $sunsetTime_a = (clone $fulltimestampdateforloop);
        $sunriseTime_a = (clone $fulltimestampdateforloop)->add(new DateInterval('P1D'));               
        
        $sunsetStr = date_sunset($sunsetTime_a->getTimestamp(), SUNFUNCS_RET_STRING, $lat, $lng, 90,$offset2);
        $sunriseStr = date_sunrise($sunriseTime_a->getTimestamp(), SUNFUNCS_RET_STRING, $lat, $lng, 90,$offset2);
        
        $ssettime = explode(":", $sunsetStr);
        $sunsetStr_h = $ssettime[0];
        $sunsetStr_m = $ssettime[1];                
        
        $srisetime = explode(":", $sunriseStr);
        $sunriseStr_h = $srisetime[0];
        $sunriseStr_m = $srisetime[1];

        $sunsetTime_e = (clone $fulltimestampdateforloop)->setTime($sunsetStr_h,$sunsetStr_m);
        $sunriseTime_e = (clone $fulltimestampdateforloop)->add(new DateInterval('P1D'))->setTime($sunriseStr_h,$sunriseStr_m);
        
        if ($fulltimestampdateforloop > $sunsetTime_e && $fulltimestampdateforloop < $sunriseTime_e) {
            $nightmin="Night";
        } else{
             $nightmin="Day";
        }
        echo 'Current Time:'.$fulltimestampdateforloop->format('Y-m-d H:i:s').' | Location: '.$lat.','.$lng.' | Sunset Start: '.$sunsetTime_e->format('Y-m-d H:i:s').' | Sunrise Start: '.$sunriseTime_e->format('Y-m-d H:i:s').' | Night or Day? :  '.$nightmin."<br>";
        $fulltimestampdateforloop->modify('+1 minutes');
    }
?>

【问题讨论】:

    标签: php time


    【解决方案1】:

    您计算出的日出时间是在日落之前

    请参阅此示例以获取说明:

    <?php
    
    $today = new DateTime;
    $randomAfternoonTime = (clone $today)->setTime(13, 25);
    $randomNightTime = (clone $today)->add(new DateInterval('P1D'))->setTime(2, 23);
    
    // Times relevant to Amsterdam on 2020-09-23.
    // Sunset happens this evening.
    $sunsetTime = (clone $today)->setTime(19, 36);
    // Sunrise happens tomorrow, so add one day.
    $sunriseTime = (clone $today)->add(new DateInterval('P1D'))->setTime(7, 30);
    
    echo "Sunset at:\n" . $sunsetTime->format('Y-m-d H:i') . "\n\n";
    echo "Sunrise at:\n" . $sunriseTime->format('Y-m-d H:i') . "\n\n";
    
    echo "Some time in the afternoon (NOT in between sunset/sunrise):\n" . $randomAfternoonTime->format('Y-m-d H:i') . "\n\n";
    echo "At night (in between sunset/sunrise):\n" . $randomNightTime->format('Y-m-d H:i') . "\n\n";
    
    // Shows bool(false): 13:25 is not in between sunset/sunrise.
    var_dump($randomAfternoonTime->getTimestamp() > $sunsetTime->getTimestamp() && $randomAfternoonTime->getTimestamp() < $sunriseTime->getTimestamp());
    
    // Shows bool(true): 02:23 is in between sunset/sunrise.
    var_dump($randomNightTime->getTimestamp() > $sunsetTime->getTimestamp() && $randomNightTime->getTimestamp() < $sunriseTime->getTimestamp());
    

    观看此 3v4l 现场演示:https://3v4l.org/lLUfL

    更新

    我冒昧地重构了您的代码,如下所示。我故意留下了我认为是你的逻辑错误的地方。我的代码输出如下:

    当前时间:2020-09-22 23:58:00 地点:50.1776906598, -51.077228098126 日落开始:2020-09-22 23:18:17 日出开始:2020-09-23 11:16:49 晚上还是白天? : 晚上

    当前时间:2020-09-22 23:59:00 地点:50.202093865458, -50.984342445684 日落开始时间:2020-09-22 23:17:55 日出开始时间:2020-09-23 11:16:27 晚上还是白天? : 晚上

    当前时间:2020-09-23 00:00:00 地点:50.226422634856, -50.891362177619 日落开始时间:2020-09-23 23:15:20 日出开始时间:2020-09-24 11:17:36 晚上还是白天? : 天

    当前时间:2020-09-23 00:01:00 地点:50.25067682914, -50.798287405434 日落开始时间:2020-09-23 23:14:57 日出开始时间:2020-09-24 11:17:14 晚上还是白天? : 天

    2020-09-23 00:00:00 和 2020-09-23 00:01:00 都说明了这个问题,不应该在 UNIX 时间戳上进行比较,而应该只在时间上进行比较。因为 00:01:00 和 00:00:00 都在日落/日出时段(“夜晚”)内,但您正在比较完整的日期时间。你很近。如果您需要任何其他帮助,请告诉我。

    重构代码(故意留下错误):

    <?php
    
    $referenceDateTime = new DateTime('2020-09-22 23:58:00');
    
    $coordinates =
        [
            [ 50.1776906598, -51.077228098126 ],
            [ 50.202093865458, -50.984342445684 ],
            [ 50.226422634856, -50.891362177619 ],
            [ 50.25067682914, -50.798287405434 ]
        ];
    
    foreach ($coordinates as $coordinate)
    {
        [ $lat, $long ] = $coordinate;
    
        $sunsetDateTime = (clone $referenceDateTime)->setTimestamp(date_sunset($referenceDateTime->getTimestamp(), SUNFUNCS_RET_TIMESTAMP, $lat, $long, 90, 2));
        $sunriseDateTime = (clone $referenceDateTime)->setTimestamp(date_sunrise((clone $referenceDateTime)->add(new DateInterval('P1D'))->getTimestamp(), SUNFUNCS_RET_TIMESTAMP, $lat, $long, 90, 2));
        
        $daySegment = ($referenceDateTime > $sunsetDateTime && $referenceDateTime < $sunriseDateTime)?'night':'day';
        
        echo "Current Time: {$referenceDateTime->format('Y-m-d H:i:s')}\nLocation: $lat, $long\nSunset Start: {$sunsetDateTime->format('Y-m-d H:i:s')}\nSunrise Start: {$sunriseDateTime->format('Y-m-d H:i:s')}\nNight or day? : $daySegment\n\n";
        
        $referenceDateTime->add(new DateInterval('PT1M'));
    }
    

    更新 2

    想自己弄清楚,所以继续写下以下内容,以帮助您正确思考:

    <?php
    
    $referenceHour = 22;
    $referenceMinute = 31;
    
    $sunsetHour = 23;
    $sunsetMinute = 50;
    
    $sunriseHour = 7;
    $sunriseMinute = 30;
    
    $referenceHour -= ($referenceHour < 12)?-12:12;
    $sunsetHour -= ($sunsetHour < 12)?-12:12;
    $sunriseHour -= ($sunriseHour < 12)?-12:12;
    
    $referenceTime = ($referenceHour * 60) + $referenceMinute;
    $sunsetTime = ($sunsetHour * 60) + $sunsetMinute;
    $sunriseTime = ($sunriseHour * 60) + $sunriseMinute;
    
    $daySegment = ($referenceTime >= $sunsetTime && $referenceTime <= $sunriseTime)?'night':'day';
    
    echo "Reference time: " . sprintf('%02d:%02d', $referenceHour, $referenceMinute) . ", sunset time: " . sprintf('%02d:%02d', $sunsetHour, $sunsetMinute) . ", sunrise time: " . sprintf('%02d:%02d', $sunriseHour, $sunriseMinute) . ", night/day: $daySegment\n";
    

    【讨论】:

    • 啊,我明白了!那么我应该在当前时间上加一天并计算第二天的日出吗?
    • 是的。您可以在DateTime 对象上使用add 方法,该对象接受DateInterval 对象。它的构造函数接受particular format 中的字符串。你很可能想要P1D。如果有帮助,请考虑将我的答案标记为已接受:)。
    • 完美。不敢相信我怎么错过了,非常感谢 Ro,真的很感激。
    • 刚试了一下,由于日出时间大于当前时间,午夜后出现同样的问题。
    • 我故意让我的补充有点罗嗦,所以你可以看到步骤。他们应该是相当自我评论的。您可以将此逻辑插入您的代码中,您应该一切顺利。如果可行,请考虑将我的答案标记为已接受:)
    猜你喜欢
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2013-03-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    相关资源
    最近更新 更多