0

Background:

I am trying to schedule a task for sending mails to my users in a project. I want to automate this task by sending mails at 2 A.M. EST daily.

My Code:

I can't really think of a good code really but I am doing this:

 DateTime.Now.AddHours(hours);

But the problem is that when I deploy this code to the server it takes DateTime.Now i.e. the deployment time and adds hours to that time.

How can I go about a clean solution?

Community
  • 1
  • 1
Bhushan Firake
  • 9,338
  • 5
  • 44
  • 79

3 Answers3

3

To work with local time you need the time zone:

var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

To get the schedule time which you express in local time you need to get the current local time and decide when to schedule next:

var estNow = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, timeZoneInfo);
var estScheduleAt = estNow.Date + TimeSpan.FromHours(2);

Now estScheduleAt will be 2 AM today in EST. If this code executes between 12 AM and 2 AM EST you should schedule the next action at this time. However, if the current time currently is after 2 AM EST you should schedule at 2 AM tomorrow (still in EST) so you need to add a day to the time:

if (estScheduleAt <= estNow)
  estScheduleAt += TimeSpan.FromDays(1);

This algorithm may fail if it run just before 2 AM EST because the predicate estScheduleAt <= estNow is true but before the action is scheduled it is in the past. You may need to add some additional handling for this situation.

Before scheduling the action you should convert back to UTC to avoid any time zone problems:

var scheduleAt = TimeZoneInfo.ConvertTimeToUtc(estScheduleAt, timeZoneInfo);

Now you can use the scheduleAt timestamp with your scheduler to make your action run at next 2 AM EST.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
  • Can you please explain what you are doing in the if statement : `if (estScheduleAt <= estNow) estScheduleAt += TimeSpan.FromDays(1);`? – Bhushan Firake Oct 14 '13 at 11:26
  • @BhushanFirake: I have expanded my answer. – Martin Liversage Oct 14 '13 at 11:31
  • 1
    Good answer. But you also need to watch out for daylight saving time transition dates. For example, on March 10 2013, 2:00 AM did not happen, and if you had scheduled for 1:00 AM then you would find on November 3rd 2013 that it occurred *twice*. See [here](http://www.timeanddate.com/worldclock/clockchange.html?n=179&year=2013) and [here](http://stackoverflow.com/tags/dst/info). – Matt Johnson-Pint Oct 14 '13 at 16:54
0

Use DateTime.UtcNow and add hours to that.

It's a good idea to do everything in UTC time and conver it to local time at your code entry & exit points.

Carra
  • 17,808
  • 7
  • 62
  • 75
0

I have done with Quartz.Net scheduler

For configuration I use CronMaker for expressions

Sample Code

// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();

// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();

// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(HelloJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTimeUtc = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);  
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger); 

Check Quartz.net setup in an asp.net website

Community
  • 1
  • 1
Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120