I have a windows service and I would like to insert a timer. How can I check if the present time is 9:00 AM ?
I would like my service to check this every day. Thank you a lot
My try:
Datetime dt=Datetime.parse("09:00:00 everyday");
if(datetime.now -dt ==0)
{
//fire event
}
Thats kinda sily of me though.
You need to make a timer and sets its interval to the timespan between now and tomorrow 9:00 AM. Next time the timer tick, set the interval again in the same way.
You should use this Timer class:
http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
Please use DateTime.UtcNow.Hour to check current hour
By using UtcNow you will gets a DateTime object that is set to the current date and time on the computer, expressed as the Coordinated Universal Time (UTC).
var now = DateTime.Now;
var today = now.Date;
var nineAm = today.AddHours(9);
TimeSpan ts = nineAm - now;
var timeInMillisecondsTill9Am = ts.Milliseconds;
If(timeInMillisecondsTill9Am==0)
{
//your code goes here
}
Since you don't know when someone may shutdown or reboot your computer or service then you need to make sure that you use a method robust enough to handle these kinds of interruptions.
I suggest that when your service checks every 5 minutes or so if the time is after 9am and if the last run date is yesterday. If so, you update the last run date to day (perhaps in a simple text file) and then run the "9:00am" task. In this way your task only runs once per day, fairly close to 9am, and is robust against reboots.
You'll need to use a standard .NET timer to trigger the checks - and if you're clever enough you can make it fire a few seconds after 9am.
Let me know if that's a good solution.
Related
I am working on a C# console application in which I need to know the ellapsed time since the program has started.
I have a variable that stores the time on start (DateTime now = DateTime.Now;)
What is the most efficient way of measuring the ellapsed time?
The ellapsed time can be hours - this is why I am concerned about efficiency and memory usage.
Thanks in advance!
Subtract the current time from the time the program started. This will return a TimeSpan which exposes properties like TotalHours which you can use to calculate the elapsed time.
// on start
var startTime = DateTime.UtcNow;
// later on, to see hours elapsed since then
var elapsed = (DateTime.UtcNow - startTime).TotalHours;
Don't worry. Measuring a time span does not use any resources, as it just compares now with then.
DateTime start = DateTime.Now;
// do some heavy calculation
TimeSpan delta = DateTime.Now - start; // get the time that elapsed
This does not use any resources except the variable for the start, which is just a 64 bit counter.
Note that for short timespans you're better off using Stopwatch, as this is not subject to time adjustments that may happen between start and now.
I have a program that checks for the date and minute part of my job object. If these match then it triggers a particular job.
If jb.ScheduledStartTime.Value.ToString("MM/dd/yyyy mm") =
Now().ToString("MM/dd/yyyy mm") Then
'Do some work here.
End If
Issue:
If I schedule different jobs during the day at different time interval then they just work fine. I mean they are triggered and in the above code they enter the loop when it matches the current format.
However, it doesn't work when the date changes at 12:00. Even though I have scheduled start time set to trigger at 9:00 AM in the morning it enters the loop exactly at 12:00 AM which is invalidating my logic leaving me confused.
Why is this happening? Is my date and minute checking logic incorrect here? Is there any better way of doing this?
I don't check for exact seconds here I just check for the minute part.
Are you checking for a change in the day etc? Is your schedulestarttime getting changed correctly after it's been triggered.
BTW don't compare times as strings. It's painful and you will get hurt. Use TimeSpan you can then get how long things were.
If datetime.now > jb.ScheduledStartTime then
'Do Some work.
end if
If you need smaller checks
dim myDateCheck as Datetime = datetime.now
myDateCheck = myDateCheck.AddSeconds(-myDateCheck.Second)
if myDateCheck > jb.ScheduledStartTime then
'Do Some work
end if
Also check the hour part (HH) of the dateteime, your format should be "MM/dd/yyyy HH:mm"
try this
If jb.ScheduledStartTime.Value.ToString("MM/dd/yyyy HH:mm") =
Now().ToString("MM/dd/yyyy HH:mm") Then
'Do some work here.
End If
I have never created a reminder application. Here is how I see it. Please let me know if I'm on the right way.
So I have users from different timezones.
ID DateTimeUTC TimeZoneID
1 2011-07-12 02:15:15.000 TimeZneID1
2 2011-07-13 16:00:00.000 TimeZneID2
3 2013-11-03 17:00:00.000 TimeZneID3
4 2011-08-22 03:00:00.000 TimeZneID4
5 2011-07-16 22:00:00.000 TimeZneID5
Create a scheduled process to run every 15 mins and do the steps below:
Get records;
The second is to convert DateTimeUTC to Time for the right timezone
Compare if it's match
a. Send Reminder
var tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZneID1);
var local = TimeZoneInfo.ConvertTimeFromUtc(DateTimeUTC, tzi);
var timeNow = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Now, tzi);
if(local == timeNow)
SendReminder();
Is it efficient way? is it the right way?
If date/time values are already in UTC in the database, you don't need to perform any conversions, surely... you just need to see whether the current UTC instant is a match, and if so, send the reminder.
That's assuming you really mean it's UTC in the database, i.e. you've converted it from the user's local time when they entered the reminder (assuming they did so to start with).
Typically, when dealing with dates like this, you would do all of your calculations in UTC and only switch to local time when it's time (no pun intended) to display the results. I assume from your question that this is a centralized database that's managing all the tasks, and you just need them to run at the correct local time?
if ( dateTimeUtc == DateTime.UtcNow )
{
// If your reminder needs to display the local time, pass it in:
var tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZneID1);
SendReminder(TimeZoneInfo.ConvertFromUtc(DateTime.UtcNow, tzi));
}
Note that DateTime.Now is in local time; you want DateTime.UtcNow for consistancy across time zones.
Another thing to be aware of is you are only running your task scheduler every 15 minutes, so the odds of times like 02:15:15 matching exactly are slim. What you would typically want to do is check for any reminder times that came up since the last run:
var currentRun = DateTime.UtcNow;
foreach ( dateTimeUtc in GetReminderDateTimes() )
{
if ( dateTimeUtc > lastRun && dateTimeUtc <= currentRun )
{
}
}
lastRun = currentRun;
In my opinion you might be over-complicating it. Since you are storing things in UTC, have the reminders in UTC, and match on UTC. Then just associate the reminders with the users that you want to remind.
I want to do similar stuff and have been debating what would be an appropriate approach. Essentially, I am writing an application which would send a message for a particular country at midnight (localtime). I have about 100 such countries and I have to also be mindful of daylight savings. I can only think of 2 ways to do this,
1. Create a corresponding thread for each country and which wakes up every hour or so and checks if it is midnight(local time) and send out the message. So essentially, I will be creating 100 threads doing nothing most of the time.
2. In this approach, there will be only one timer which checks every minute or 30 secs the local time for 100 countries and send message. There will need to be some extra logic as there will never be an exact midnight match.
Not sure, if there is any better way to tackle above situation. It would be great if I can get some ideas/suggestions here.
Thanks,
SP.
I am using System.Timer to trigger an event. Currently I trigger it every 1 hour and check if it matches the configured value (day,time).
But it is possible to trigger this at a specific time? like suppose on Sunday at 12Am.
Windows Task Scheduler would be more appropriate but its not an option.
Thanks in advance
It isn't clear why you just wouldn't set the timer's Interval to the target date/time. There's a limit on the number of milliseconds, you can time up to 2^31 milliseconds, 27 days. You'll be good as long as you can stay in that range.
private static void SetTimer(Timer timer, DateTime due) {
var ts = due - DateTime.Now;
timer.Interval = ts.TotalMilliseconds;
timer.AutoReset = false;
timer.Start();
}
The timer doesn't support this kind of interval but you could check every 20 seconds for the current day and time.
Edit Sorry you are doing that already... why not make the interval half the time left each time you check (A Zeno timer)?
In a similar situation, I'm using System.Threading.Timer to achieve this. Basically I set its due time to desiredDateTime - DateTime.Now, so that it will tick at desiredDateTime.
If you get another date meanwhile, you can user Timer.Change() to change the tick time to the new date. Don't forget to Dispose() the Timer when you no longer need it!
I'm developing an application and I need to get the current date from a server (it differs from the machine's date).
I receive the date from the server and with a simple Split I create a new DateTime:
globalVars.fec = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, int.Parse(infoHour[0]), int.Parse(infoHour[1]), int.Parse(infoHour[2]));
globalVars is a class and fec is a public static variable so that I can access it anywhere in the application (bad coding I know...).
Now I need to have a timer checking if that date is equal to some dates I have stored in a List and if it is equal I just call a function.
List<DateTime> fechas = new List<DateTime>();
Before having to obtain the date from a server I was using computer's date, so to check if the dates matched I was using this:
private void timerDatesMatch_Tick(object sender, EventArgs e)
{
DateTime tick = DateTime.Now;
foreach (DateTime dt in fechas)
{
if (dt == tick)
{
//blahblah
}
}
}
Now I have the date from the server so DateTime.Now can't be used here. Instead I have created a new timer with Interval=1000 and on tick I'm adding 1 second to globalVars.fec using:
globalVars.fec = globalVars.fec.AddSeconds(1);
But the clock isn't accurate and every 30 mins the clock loses about 30 seconds.
Is there another way of doing what I'm trying to do? I've thought about using threading.timer instead but I need to have access to other threads and non-static functions.
Store the difference between the server's time and local time. Calculate the servers' time when you need it using that difference.
If you create atimer with an interval of 1000ms, it will be called no sooner than 1000ms. So you can pretty much guarantee that it will be called in more than 1000ms, which means you will "lose" time by adding 1s on this timer tick - This will accumulate error with every tick. A better approach is to record a start time and use the current time to determine the current offset from that known start time, so that you don't accumulate any error in your time keeping. (There will still be some error, but you will not drift out of touch with real-time over time)
Different timers (Forms.Timer, Thread.Timer etc) will give different accuracies as well - Forms.Timer is particularly poor for accuracy.
You could also use a high performance time to keep track of the time better - see here, for example.
Here is a reliable 1 μs Timer
See https://stackoverflow.com/questions/15725711/obtaining-microsecond-precision-using-net-without-platform-invoke?noredirect=1#comment22341931_15725711
I guarantee its faster and more accurate then StopWatch and PerformanceCounters and uses the fractions of a second you have in the time slice wisely!