How to evaluate when two DateTimes are equal to one another - c#

This is the situation: I have a TimePicker in my application. I would like the user to be able select a time with the TimePicker, then the app will send the user a notification at the time entered with the TimePicker. I'm writing an application for Windows Phone in C#. So far, this is my code (I don't that any of this is correct)
DateTime now = DateTime.Now;
DateTime? get = timePicker1.Value;
if (now == get)
{
ShellToast toast = new ShellToast();
toast.Title = "Title";
toast.Content = "The Time Has Come!";
toast.Show();
}
But every time I run the code, it either gives me an exception, the app doesn't load at all, and every time the notification (toast) never shows. (I also know that the app cannot be running in the foreground for the notification to show). (I know that the notification works because I can get it to work with other situations).
Basically, my questions is: how can I trigger a notification at a specific time defined by the end user?

First of all the Toast notification won't show up if the app is running in foreground. It should be only used in background agents or when application is running under lock screen.
Second, if your goal is to show the notification in selected time of day, then you must not compare the DateTime values, but rather the TimeOfDay part. Also make sure user has entered valid value by checking the "get.HasValue"

Line 1 : DateTime now = DateTime.Now;
Line 2 : DateTime? get = timePicker1.Value;
in Line 1 , you get the system current date-time, "now" is date-time and not null.
but in Line 2, "get" is null-able variable and you are getting the timepicker.value and compare date-time with time.
i do not know what exception you have but with 2 extra checking you can have more safe code
null checking for "get"
make sure that in your development environment you can compare date-time with time value.

You have to remember that Date.Now has a full time AND DATE!
So comparing to the get variable you must ignore the Date part, or probably will not work.
Try changing your if to look something like this:
if (get.HasValue && now.TimeOfDay == get.Value.TimeOfDay)
{
// your remaining code
}
Also, the ShellToast class only works with background services, not on foreground apps (check the Remarks here)!
If you want to show a Toast in your app, use the Toast Prompt from Coding4Fun Toolkit.

You could compare the day, month, year values of the two DateTimes. Take minutes and seconds in account, if you want to be more precise (because I don't know on what detail level you want to compare the values).
If you want to be notified at a specific time, try using the Alarm class.

Related

Making A Cool Down Timer For Multiple Users

So I'm currently developing a Discord Bot, and I have a problem on how I could make a cool down timer for a command. So I want it so if they use a command, then they get added to a list, and have to wait amount of seconds until they can use the command. I have a somewhat idea on how to do this, but I'm mainly stuck at the part of having multiple cool down timers for different people. So lets say as a reference. User1 uses the command, now he has to wait 5 seconds until he uses it again. Then User2 uses the command, and he also has to wait 5 seconds. Well User2 used the command 3 seconds in of the cool down for User1. So basically I'm asking how could I make a timer that kept track of each users time. Then once that specific users cool down is done, he gets removed from a list. I planned to store the users that are on cool down into a list.
I might be overthinking this, so sorry.
The way that I did it was by making it so the program declares 2 empty lists near the start, one containing DateTimeOffset and the other SocketGuildUser. You could tie the two into a list of object instances, if you want your code to be a little more efficient and bug-resistant. For the sake of the example however:
Declare your lists at the start of your program.
public static List<DateTimeOffset> stackCooldownTimer = new List<DateTimeOffset>();
public static List<SocketGuildUser> stackCooldownTarget = new List<SocketGuildUser>();
Here's the rate limit code:
//Check if your user list contains who just used that command.
if (Program.stackCooldownTarget.Contains(Context.User as SocketGuildUser))
{
//If they have used this command before, take the time the user last did something, add 5 seconds, and see if it's greater than this very moment.
if (Program.stackCooldownTimer[Program.stackCooldownTarget.IndexOf(Context.Message.Author as SocketGuildUser)].AddSeconds(5) >= DateTimeOffset.Now)
{
//If enough time hasn't passed, reply letting them know how much longer they need to wait, and end the code.
int secondsLeft = (int) (Program.stackCooldownTimer[Program.stackCooldownTarget.IndexOf(Context.Message.Author as SocketGuildUser)].AddSeconds(5) - DateTimeOffset.Now).TotalSeconds;
await ReplyAsync($"Hey! You have to wait at least {secondsLeft} seconds before you can use that command again!");
return;
}
else
{
//If enough time has passed, set the time for the user to right now.
Program.stackCooldownTimer[Program.stackCooldownTarget.IndexOf(Context.Message.Author as SocketGuildUser)] = DateTimeOffset.Now;
}
}
else
{
//If they've never used this command before, add their username and when they just used this command.
Program.stackCooldownTarget.Add(Context.User as SocketGuildUser);
Program.stackCooldownTimer.Add(DateTimeOffset.Now);
}
From here, type whatever you want your code to do if they pass.

Automatic update custom DateTime object based on system time

I think my question is a bit confusing as I'm not really sure how should I give it a proper title.
Anyway, my question is because I'm getting current date on my server instead of system time (or device's time). How can I make it to act like a "clock"?
For example:
// I have a string of date retrieved from server, let's call it as "stringFromServer"
myDate = Convert.ToDateTime(stringFromServer);
So after the above line of codes, I need myDate to update every seconds so that I can use it anytime I want.
Let say the current time (get from myDate) is 09:00 and after 5 seconds I expect it to be updated to 09:05.
One of the solution I have in mind is in my Update() function,
I'll do something like this:
myDate.Value.AddSeconds(deltaTime);
But I'm looking for better solution and hopefully I can get some help here.
PS: The reason I'm not using system time is to prevent user changing the time in device's settings. So I have to update myDate whenever the user exit or reopen the app.
In Unity3D, if you want an event to happen every X seconds, a good way to do that is to use an IEnumerator function. So for example, if you want to keep track of a custom time variable you could have an IEnumerator like this:
IEnumerator UpdateServerTime()
{
while(true)
{
myDate.Value.AddSeconds(1);
yield return new WaitForSeconds(1);
}
}
This example would continue to update your time varable by one second, every second. As other users have mentioned in the comments, this is not the perfect way to keep track of time. But it should achieve what you want, if you are looking to track time in unity.
It is important to remember that in order to use this method properly, you need to call it like so:
StartCoroutine(UpdateServerTime());

C# Timer to run even if system is switched off or restarted

I am trying to create a script which does something say show a popup after 1 day. As far as I know I can do this using Thread.Stop or using System.Timers or many other ways. But the problem with each is that the computer has to be continuously running for each of these methods to give desired result at the time I want. Basically I want the script to start with installation of my program, wait for exactly 24 hours, then display a message box. If the computer is switched on at that time i.e. after 24 hours it should show the message box on next start up but only if 24 hours or more have passed. Please help, i am unable to find suitable solution for this. any help will be highly appreciated. I think that it may be achieved by getting the dateTime.Now and putting it in a file, and then compare current system time to the time in file every hour or so, and if 24 hours or more have passed, show the message box. Please help
If a message box is what you need to pop up, then you'll need a Windows Forms application. Here is the workflow of how it'll work:
Application will need to save data, either through a database or to a file.
When the application first loads, it will check either the database or the file for a TriggerDate entry.
If the TriggerDate exists, pull this date and compare it to today's date and time. If the current date and time is past our TriggerDate, display the message box. Recreate the TriggerDate with the current date and time plus 24 hours.
If TriggerDate does not exist, create it, filled with the current date and time plus 24 hours (e.g. DateTime.Now.AddHours(24)).
Use Threading.Thread.Sleep() to sleep for 5 minutes.
Jump to step 3 and repeat.
EDIT
Code will be something like this:
private const string TriggerFile = #"C:\TriggerData\trigger.txt";
private DateTime _triggerDate;
if (!File.Exists(TriggerFile))
{
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
}
}
using (StreamReader sr = File.OpenText(TriggerFile))
{
_triggerDate = DateTime.Parse(sr.ReadToEnd());
}
while (true)
{
if (DateTime.Now >= _triggerDate)
{
MessageBox.Show(#"Alert!");
using (StreamWriter sw = File.CreateText(TriggerFile))
{
sw.WriteLine(DateTime.Now.AddHours(24));
_triggerDate = DateTime.Now.AddHours(24);
}
}
System.Threading.Thread.Sleep(60000*5); // Sleep for 5 minutes
}
You may not want to do while(true). You way want to implement a way to get out of the program.
If I understand correctly, what you can use is a way to save the "start date". You can save the start date of the timer and read the value from your script, that way you can calculate if 24 hours or more has passed since the moment you assigned a value to the start date. You can use a simply TXT file to save the value.
I see two ways of achieving this :
Easy way (but not strictly related to C#) is to use the task scheduler and create a task that will run your C# program every 24 hours. One way to do this from an installer would be to use the SchTasks.exe tool. This method allows you to just exit the program after your work is done without having to explicitely wait for the next run.
Harder way: Create a Windows Service, which is a program specifically designed to run permanently on the host computer. These programs are slightly more technical to write though. You can find more explanations about services here. However, you may not want to take this route as service cannot display user interfaces like popups.

Find last occurrence of an event in DDay.iCal

Suppose I have an iCalendar with a single event. This has a recurrence rule (RRULE) set with a COUNT to limit it, but also has some exception dates, and some exception rules.
I want to calculate the date of the last occurrence.
If the rules only had UNTILs set, this would be easy as I would know that this bounded the possible dates, so I could do the following.
IICalendar calendar = LoadCalendar();
Event evt = calendar.Events.Single();
DateTime start = evt.Start;
DateTime end = evt.RecurrenceRules.Select(r => r.Until).Max();
var lastOccurrence = evt.GetOccurrences(start, end).Last();
However, this approach will not work with a COUNT, as the exceptions can push the last occurrence indefinitely into the future (e.g. assume the first 500 dates of a weekly occurrence have been excluded - this would push the end date about 10 years into the future).
Is there a straightforward way to determine the last occurrence in this scenario? (Ultimately, I could write my own rule parser, or reflect on the one built into DDay, but I'm hoping for an easier way!).
Background
For reference, I am aiming to build a Quartz.NET Trigger which uses an iCalendar file to determine when to fire.
The COUNT is associated only with the RRULE, not to the event as a whole. See rfc5545#section-3.8.5.3 :
The
final recurrence set is generated by gathering all of the start
DATE-TIME values generated by any of the specified "RRULE" and
"RDATE" properties, and then excluding any start DATE-TIME values
specified by "EXDATE" properties.
You first build a set based on the RRULE (including its COUNT value), and then you remove the ones that are mentioned in EXDATE.
In other words, if you have an RRULE with a COUNT of 500 and 100 EXDATE instances, you end up with 400 instances.
Just FYI, you mention exception rules but EXRULE has been deprecated in RFC5545.

Set Expiring Date To .NET Output (Without Hardware Dongles)

My first solution for this problem is to use OS/BIOS timer and check it with encrypted date file ( see below pseudocode )
public void CheckFrequently()
{
DateTime registeredDate = ReadFromBiosOrOSTimer();
DateTime readEncryptedDate = ReadFromEncryptedFile();
if(registeredDate >= readEncryptedDate)
{
ShowExpireDateForm();
CloseProgram();
}
}
In this case its obvious that user could change OS/BIOS timer easily and my method not works.
my questions are :
Is there any way to fix user OS/BIOS timer change problem?
Is there any better way to set expiration date to .Net projects?
(My answer is assuming you want to have an "expiring" program of some sort.)
The end-all-be-all big brother answer would be to retrieve a trusted time from an external source, say, a web service. Of course, connectivity (or lack thereof) may make this impossible.
Other than that, knowing that if someone is going to cheat the clock, they would likely do it very close to the expiration, periodically write, somewhere, a timestamp of the current time. If you ever encounter a case where the retrieved (via system call) time is less than the last timestamp, someone might be trying to trick the clock and you can invalidate the session/instance with the appropriate error message. Once you've detected the "expired" case, it's simple to flip a switch and refuse to run anymore.
All of that said, a countermeasure like this will most likely always be beaten by an adversary who is determined enough.

Categories