duanhe2027 2009-11-17 20:01
浏览 38
已采纳

PHP 5.3 DateTime用于重复发生的事件

I have a calendar application which utilizes the newer PHP DateTime classes. I have a way that I handle recurring events, but it seems hack-ish and I wanted to see if you guys have better ideas:

  1. I have a recurring event that starts 11/16/2009 (Nov 16, 2009)
  2. It will occur every 3 days
  3. The event will recur indefinitely

Let's say the user looks at the calendar for Dec, 3100 - this event should show there repeating every 3 days like normal. The question is - how do I calculate those days in that month?

=========================================

This is how I basically do it, but I know I'm missing something easier:

  1. I calculate the difference in days between the start of the month being looked at (Dec 1, 3100) and the event start date (Nov 16, 2009) stored as $daysDiff
  2. I subtract the modulus, so that I get a factor of 3 days from the start like this: $daysDiff - ($daysDiff % 3)
  3. For the sake of argument lets say that gives me Nov 29, 3100 as a date.
  4. I then add 3 days to that date repeatedly until I have all the dates within Dec 3100

My main problem comes with step 1. The PHP DateInterval::date_diff function does not calculate differences in days. It will give me years, months, and days. I then have to fudge the numbers to get an estimate date around Dec, 3100. 11/16/2009 + (1090 years * 365.25 days) + (9 months * 30.5 days) + 15 days

When you go REAL far into the future like the year 9999, this estimation can be off by a month, then I have to subtract a lot of 3 day intervals to get where I need.

  • 写回答

2条回答 默认 最新

  • dongmangzong8006 2009-11-17 21:01
    关注

    You could format your date as a unix timestamp then use modular division to find the first instance in the selected month, then step in increments of 3 days from there. So for your example:

    $startDate = new DateTime(20091116);
    $startTimestamp = $startDate->format('u');
    $recursEvery = 259200; // 60*60*24*3 = seconds in 3 days
    
    // find the first occurrence in the selected month (September)
    $calendarDate = new DateTime(31000901); // init to Sept 1, 3100
    while (0 != (($calendarDate->format('u') - $startTimestamp) % $recursEvery)) {
        $calendarDate->modify('+1 day');
    }
    
    $effectiveDates = array();
    while ($calendarDate->format('m') == 9) {
        $effectiveDates[] = clone $calendarDate;
        $calendarDate->modify('+3 day');
    }
    
    //$effectiveDates is an array of every date the event occurs in September, 3100.
    

    Obviously, you've got a few variables to swap out so the user can select any month, but that should be the basic algorithm. Also, ensure your DateTimes are the correct date, but with the time set as 00:00:00, or else the first while loop will never resolve. This also assumes you've ensured the selected date is later than the beginning date of the event.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 GD32 SPI通信时我从机原样返回收到的数据怎么弄?
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式
  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?