Hi All

I have a use case which involves sending an sms (using sms_framework) to a user at a given time each day. The user sets the time and the message in their user profile node (I'm using content_profile) and I have triggered rules which fire when a profile is saved or updated. These schedule a ruleset to send the message which then re-schedules itself for the next day.

I am storing both the send time and the message as CCK text fields in the user's content profile.

The time field is configured to use a select widget with 15 minute increments i.e. it has values "00:00,00:15,00:30...23:30,23:45".

I have the site's cron running every fifteen minutes too.

There are a number of issues with this:

  1. When the triggered rule schedules the ruleset, if I use only the token for the cck time field [node:field_time] to determine the scheduled time then the ruleset will be scheduled for today at the given time. This works correctly even if the user has a different timezone to the site as the user's timezone is in effect when the rule is triggered. However, if the scheduled time has already passed then the ruleset runs on the next cron run and the sms is sent immediately. e.g. if a user logs in at 3:05pm to change their SMS time to 08:30 (am) then the ruleset is scheduled for 08:30am today and is thus sent on the next cron run at 3:15pm.

  2. When the ruleset re-schedules itself I can use "+24 hours" as the scheduling time, but this gives me a schedule time of 24 hours after the ruleset fires - so if the ruleset is scheduled in the past (see point 1) then it is rescheduled 24 hours after this time - which could be completely different from the intended time e.g. in the above case it would be re-scheduled for 3:15pm the following day instead of 8:30am. I can try to fix this by setting the re-scheduled time to "tomorrow [node:field_time]" - but this has the problem that when the ruleset is run the timezone in effect is the site's time zone not the user's - so the ruleset would be re-scheduled for the wrong time.

What I ended up doing was to write a mini-module with a php function to calculate the timestamp of the next sms time in the user's time zone:

function MYMODULE_sms_schedule_time($time,$user) {
        $timezone=$user->timezone_name;
        $today = "today ".$time." ".$timezone;
        $tomorrow = "tomorrow ".$time." ".$timezone;
        $schedule = strtotime($today)>time()?strtotime($today):strtotime($tomorrow);
        return $schedule;
}

When the triggered rule is fired or the ruleset is re-scheduled I use a php snippet to call this function with the cck time field value and the user object (loaded with a rules action).

Just to be thorough I also added a triggered rule to re-schedule the ruleset if the user updated their account's timezone.

This seems to work fine and the sms messages are being sent at the correct times.

I just wondered if anyone could see a better way of doing this other than writing my own php code to calculate the scheduled time - it seems like the sort of use case that I should be able to do with rules without resorting to coding?

Cheers

Comments

TR’s picture

Version: 6.x-1.4 » 7.x-2.x-dev

It sounds to me like the problem you are having is scheduling the first execution of your Rule - after the first execution it sounds like the Rule operates properly.

There are several things you can do to make that first execution happen at the correct time. Basically, you have to calculate that first time and pass the calculation to the scheduler action, rather than just passing the user-entered time.

So, get the user-entered time and use the Data comparison condition to determine if the scheduled time is before or after the current time. If it is before, use the Add a variable action and the Data calculation action to add a variable with the correct offset into the future. For your example, 0830 is before 1515, so you want to schedule the execution for 2400 - (1515 - 0830) = 1715 hours into the future ("now" + 17.25 hours). You will store 17.25 in your added variable, and use that added variable in the "direct input" mode for the relative date of execution. Likewise, if the scheduled time is after your current time, just find the difference and use that as the relative date.

The timezone problem is the subject of several other issues - see for example https://www.drupal.org/project/issues/rules?text=gmt&status=Open&priorit... Rules currently doesn't handle timezones correctly, but when those issues are fixed they will be fixed for this use case as well.

TR’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.