execute command 10 seconds before alarm - c#

I am working on a project that allows me to create a program and give it tasks. Right now I am working on where I can tell it to set an alarm. The alarm feature works well, but I have a problem. When I set the alarm, I can say "goodnight" and then the program turns my monitor off into sleep mode. When the alarm goes off I want it to turn the monitor back on 10 or 15 seconds before it executes the code that happens when the alarm goes off.
Here is a bit of my code:
DateTime now = DateTime.Now;
string time = now.GetDateTimeFormats('t')[0];
if (time == Settings.Default.Alarm && Settings.Default.AClockEnbl == true)
{
SetMonitorInState(MonitorState.MonitorStateOn);
}
if (time == Settings.Default.Alarm && Settings.Default.AClockEnbl == true)
{
//All other alarm code
}
I want the first if statement to tell the command to happen 10 seconds before Settings.Default.Alarm
Can anybody help?

If you add 15 seconds to the DateTime now and compare that to the Alarm time, you can use that to turn on the monitor.
Then you can execute the rest of the code when now (without the extra 15 seconds) equals the alarm time.
As mentioned in comments you'll want to compare with DateTime's instead of strings and use TimeSpan to increment 15 seconds.

You can use a TimeSpan to offset your date:
beforeTime = now + TimeSpan.FromSeconds(15);
then compare Settings.Default.Alarm with beforeTime.GetDateTimeFormats('t')[0] in order to turn on the monitor.
This said, try to refactor your code and get rid of those strings. Use DateTime and TimeSpan or ms since Epoch in an int if you really want, but not strings.

Related

Create a recurring event at midnight using C#, Unity Game Engine

In a game, I want to trigger an event every night at midnight. The following code is not working:
void Update()
{
var tomorrow = DateTime.Now.AddDays(1).ToShortDateString();
var today = DateTime.Now.ToShortDateString();
if (tomorrow == today)
{
THE THING I WANT TO HAPPEN AT MIDNIGHT;
}
}
In debugging I have found that THE THING I WANT TO HAPPEN works fine. However, the event isn't triggering from the if statement.
I searched the archives for answers, and found some, but the solutions aren't working - this is almost certainly a simple error due to my extremely low-level programming knowledge.
Any assistance would be great...Thanks!
Your code is effectively asking "1 == 1 + 1?" and the answer will always be no.
You need to keep the last execution date stored outside the method, and you also need to be more careful how you do your comparison. For instance, DateTime.Now == DateTime.Now might return false (and pretty often), because DateTime stores the time down to the tick, and if it's off by even one tick, it won't be considered equal.
Try this:
DateTime lastExecutionDate = DateTime.Utc;
void Update()
{
var tomorrow = DateTime.Now.AddDays(1).ToShortDateString();
var now = DateTime.Utc;
if (lastExecutionDate.Day < now.Day)
{
lastExecutionDate = now;
// this code will be called as close to midnight as unity allows.
}
}
I'm not sure if it will be considered midnight immediately when the game starts. If it is, try using this for lastExecutionDate instead...
DateTime lastExecutionDate = DateTime.UtcNow + TimeSpan.FromDays(1);
if (tomorrow == today) this will never be true. If it is exactly midnight (Jan 01 2000 12:00:00.0000) then this line: tomorrow = DateTime.Now.AddDays(1) will equal midnight...tomorrow, all the time (Jan 02 2000 12:00:00.0000). The same applies to every other date-time.
You're better off checking to see if the current time is midnight, then store the current date somewhere and DoTheThing() only if it's currently midnight and the stored date is not today's date.
Of course, this also ignores the issue of "do you want the event to be triggered retroactively if the application is not actively run at midnight." In which case, TimeSpans and Last_run_date may be of interest.

Time-dependent coloring in C#

I need time-dependent coloring in a project. If the system is 10 minutes past the entrance time, the background will be orange. If it is 20 minutes past it will be red. I found the difference between the two dates using the
DateTime.Parse(timeNow).Subtract(DateTime.Parse(timeLogged));
but I can't compare the result.
if(Convert.ToInt32(DateTime.Parse(timeNow).Subtract(DateTime.Parse(timeLogged)))>10)
Does it have a similar use? Can you help me how to do it?
I am using Google Translate because my English is not very good, and I apologize for the language mistakes I made.
You can subtract DateTime objects. You'll get a TimeSpan. You can use that TimeSpan to determine the difference between the original objects:
DateTime now = DateTime.Parse(timeNow);
DateTime logged = DateTime.Parse(timeLogged);
TimeSpan diff = now - logged;
if (diff.TotalMinutes > 10)
// It's been more than 10 minutes.
You could do this aswell
// If older than 20 min
if(DateTime.Parse(timeLogged) < DateTime.Now.AddMinutes(-20))
{
// Do stuff
}
DateTime.Subtract returns a Timespan object that has a TotalMinutes property, so you could do this:
if (DateTime.Parse(timeNow).Subtract(DateTime.Parse(timeLogged)).TotalMinutes > 10)

datetime checking for specific time

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.

How to send reminders at correct time for users in different timezones?

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.

inaccurate .NET timer?

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!

Categories

Resources