I am creating a function that will set the date of an event, based on the current time.
I have an enumeration of events:
public enum EventTimings
{
Every12Hours, // 12pm and midnight
Weekly // sunday at midnight
}
public static DateTime CalculateEventTime(EventTimings eventTime)
{
DateTime time;
switch(eventTime)
{
case EventTimings.Every12Hours:
break;
}
return time;
}
So (Every12Hour event type) if the current time is 10am, then the eventdate will be the same day but at 12pm.
How should I write this?
I also have to make sure this works for December 31st and any other strange outlier date/time.
Is datetime开发者_Go百科 the best for this scenerio?
If you want to be able to test anything, I would make the DateTime you are trying to "round" explicit, something like
public static DateTime RoundedDate(DateTime eventTime, EventTimings strategy)
{
switch (strategy)
case EventTimings.Weekly :
return WeeklyRounding(eventTime);
... etc ...
That way you can now write a specialized method for the 12-hour interval, the week interval, and test it for any input date possible, without depending on your computer clock.
You could also try something like this, although it breaks down if you want to do something monthly (because months each have a different number of days.) Also, while this simplified method will ensure a returned date at 12 and midnight, the weekly offset would be every 7 days from the starting day... not necessarily on Sundays. You could easily accomodate that behavior with a switch statement, though. The overloaded method also allows you some flexibility to provide a custom offset.
Also, to answer your question, yes I would use System.DateTime and System.TimeSpan. They handle determining whether a year or month has "rolled over" for you.
public enum EventTimings : int
{
Default = 12, // Default every 12 hours.
NoonAndMidnight = 12, // Every 12 hours.
Weekly = 168, // 168 hours in a week.
ThirtyDays = 720 // 720 hours in 30 days.
}
public DateTime CalculateDateTime(DateTime starting, EventTimings timing)
{
return CalculateDateTime(starting, TimeSpan.FromHours((int)timing));
}
public DateTime CalculateDateTime(DateTime starting, TimeSpan span)
{
DateTime baseTime = new DateTime(starting.Year, starting.Month, starting.Day, starting.Hour >= 12 ? 12 : 0, 0, 0);
return baseTime.Add(span);
}
I agree to keep it generic by making the reference date an input parameter instead of current datetime. However as you have asked about the logic for your eventTime values as well, this is how I would go about.
How should I write this?
For every12hours, check the hour property of the input date and check if it is less than 12. If so, then create a new TimeSpan for 12pm and add it to the datepart of the input date. If not, add 1 day to the input date, create a TimeSpan for 12am and add it to the datepart of inputdate.
For weekly (Monday 12am), check the dayoftheweek of the inputdate and just add number of days to make it equal to the incoming Monday (Which is as simple as (8 - dayoftheweek)) and add a 12am TimeSpan to the date of the incoming Monday's date.
public enum EventTimings
{
Every12Hours, // 12pm and midnight
Weekly // sunday at midnight
}
public static DateTime CalculateEventTime(EventTimings eventTime, DateTime inputDate)
{
DateTime time = DateTime.Now;
switch (eventTime)
{
case EventTimings.Every12Hours:
time = inputDate.Hour > 12 ? inputDate.AddDays(1).Date + new TimeSpan(0, 0, 0) : inputDate.Date + new TimeSpan(12, 0, 0);
return time;
case EventTimings.Weekly:
int dayoftheweek = (int) inputDate.DayOfWeek;
time = inputDate.AddDays(8 - dayoftheweek).Date + new TimeSpan(0, 0, 0);
return time;
// other cases
}
}
Is datetime the best for this scenerio?
Yes. Your datetime calculations using DateTime and TimeSpan should take care of leap years, daylight savings or endofyear scenarios. Additionally you could try adding SpecifyKind to denote it is local time.
The algorithm I'd follow goes like this...
- Put noon on the day of
eventTime
into a variable - Check if that variable is before
eventTime
- If it's not, add 12 hours to it
Return the variable
switch (strategy) { case EventTimings.Every12Hours: //get noon for the event date DateTime x = eventTime.Date.AddHours(12); //check to see if x is after the eventTime if (x < eventTime) { //if so, advance x by 12 hours to get midnight on the next day x = x.AddHours(12); } return x; break; //other cases... }
精彩评论