This question talks about validating a string representing a date, and in it folks mention that it's good to avoid using Exceptions for regular flow logic. And TryParse() is great for that. But TryParse() takes a string, and in in my case i've already got the year month and day as integers. I want to validate the month/day/year combination. For example February 30th.
It's pretty easy to just put a try/catch around new DateTime(int, int, int), but I'm wondering if there's a way to do it without relying on exceptions.
I'd also feel silly composing these ints into a string and then using TryParse().
The following will check for valid year/month/day combinations in the range supported by DateTime, using a proleptic Gregorian calendar:
public bool IsValidDate(int year, int month, int day)
{
return year >= 1 && year <= 9999
&& month >= 1 && month <= 12
&& day >= 1 && day <= DateTime.DaysInMonth(year, month);
}
If you need to work with other calendar systems, then expand it as follows:
public bool IsValidDate(int year, int month, int day, Calendar cal)
{
return year >= cal.GetYear(cal.MinSupportedDateTime)
&& year <= cal.GetYear(cal.MaxSupportedDateTime)
&& month >= 1 && month <= cal.GetMonthsInYear(year)
&& day >= 1 && day <= cal.GetDaysInMonth(year, month);
}
Use String Interpolation
int year = 2017;
int month = 2;
int day = 28;
DateTime dt;
DateTime.TryParse($"{month}/{day}/{year}", out dt);
As far as I know, there's no easy way to check for a DateTime's int's validity besides concatenating the ints into a correctly formatted string beforehand.
To avoid try/catch-ing, I would write a static utility class which utilizes DateTime.TryParse:
using System;
public static class DateTimeUtilities
{
public static bool TryParse(int year, int month, int day, out DateTime result)
{
return DateTime.TryParse(
string.Format("{0}/{1}/{2}", year, month, day), out result);
}
}
Usage:
DateTime dateTime;
if (DateTimeUtilities.TryParse(2017, 2, 30, out dateTime))
{
// success
}
else
{
// fail, dateTime = DateTime.MinValue
}
Pending the needs of your application, e.g. culture (thanks #Matt Johnson), I would also look into DateTime.TryParseExact.
Look at it this way. Any code that you write:
Will have to check month ranges 1-12
Will have to check day ranges by month, which means you'll have to hard code an array
Will have to account for leap years, which can be a pain the the rear
Rather than doing ALL that, and reinventing the wheel, and potentially getting it wrong -- why don't you keep it simple and just wrap the DateTime constructor in a try-catch and keep it moving? Let the nerds up in Redmond do all the hard work for this common task. The best solution is one that any developer following you can understand and rely upon quickly.
I'd bet money that under the hood, TryParse and the DateTime constructor are using the exact same validators, except that the latter throws an exception while the former does not. TryParse, for this, is overkill with all the extra string manipulation involved.
Related
I realize this may have been answered before, and I may just not be searching for the answer properly, so my apologies if this is a duplicate. This is for a c# webform.
I've got a datetime, set to now, and rounded up the nearest 30 minutes:
DateTime dtNow = RoundUp(DateTime.Now, TimeSpan.FromMinutes(30));
I'm splitting the datetime into its component parts, using M:YY tt (no preceding 0 on the month, two digit year, 12 hr am/pm)
DateString = dtNow.ToString("M/dd/yy");
TimeString = dtNow.ToString("h:mm tt");
What I want do to is simple, I want to see if that TimeString falls between 7:00pm and 5:59am, just need to round it to 6:00am of the following day (unless its past midnight, in which case 6:00am of that day).
Can anyone help me out, or at least point out where its already answered?
You should really stick to DateTime. What you want using string will always need to parse again that string into a DateTime to implement your logic.
A simple solution:
public static DateTime GetRoundedDate(DateTime originalDate)
{
if(originalDate.Hour > 19)
return originalDate.Date.AddDays(1).AddHours(6);
else if (originalDate.Hour < 6)
return originalDate.Date.AddHours(6);
return originalDate;
}
So now you may call:
DateTime dtNow = RoundUp(DateTime.Now, TimeSpan.FromMinutes(30));
var rounded = GetRoundedDate(dtNow);
DateString = rounded.ToString("M/dd/yy");
TimeString = rounded.ToString("h:mm tt");
Just look at the time properties on your DateTime object.
if (dtNow.Hour >= 19 || (dtNow is tomorrow && dtNow.Hour <= 7)) {
//do your stuff
}
where "is tomorrow" is something like dtNow.Date == DateTime.Today.AddDays(1)
I'm searching for a C# equivalent to the functionality provided by the boost:gregorian generators.
Specifically, I have wildcard dates and need to convert them to concrete dates.
For example a wildcard 'Third Monday in January' could be done with boost::gregorian as
typedef nth_day_of_the_week_in_month nth_dow;
nth_dow ndm(nth_dow::third, Monday,Jan);
date d = ndm.get_date(2002);
//2002-Jan-21
By using this feature, it can then be further wildcarded as 'Third Monday every month', or '.. every odd month'.
What is the best way to achieve such behaviour in C#?
It is possible to do this straight up with DateTime.DaysInMonth foreach loop then check the day, but it can be a pain so I suggest you just set up a method such as below
public static IEnumerable<DateTime> AllDatesInMonth(int year, int month)
{
int days = DateTime.DaysInMonth(year, month);
for (int day = 1; day <= days; day++)
{
yield return new DateTime(year, month, day);
}
}
Then you can do something similar to the below code:
foreach (DateTime date in AllDatesInMonth(2016,4).Where(dt => dt.DayOfWeek == DayOfWeek.Monday))
break; //This will work as it will execute the break as soon as it hits the first monday of the month
What do you mean by wildcard dates though? TimeSpans?
I have application that needs to be run on working days, and within working hours.
In application configuration, I've set start time in format
Monday-Friday
9:00AM-5:30PM
Now, I have a problem how to check if current day is within day boundare is (for the time is easy - parse time with DateTime.ParseExact and simple branch will do), but I don't know how to parse days.
I've tried with:
DayOfWeek day = DateTime.Now.DayOfWeek;
if (day >= (DayOfWeek)Enum.Parse(typeof(DayOfWeek), sr.start_day) &&
day <= (DayOfWeek)Enum.Parse(typeof(DayOfWeek), sr.end_day))
{ /* OK */ }
sr.start_day and sr.end_day are strings
but the problem occurred during weekend testing - apparently, in DayOfWeek enum, Sunday is first day of the week (refering to the comments on MSDN page
I suppose I could do some gymnastics with current code, but I am looking for the most readable code available.
Edit
Sorry for the misunderstanding - working days are not from Monday to Friday - they are defined as strings in config file, and they can be even from Friday to Saturday - which breaks my original code.
if ((day >= DayOfWeek.Monday) && (day <= DayOfWeek.Friday))
{
// action
}
From Hans Passant's comment on my original question:
Just add 7 to the end day if it is less than the start day. Similarly,
add 7 to day if it is less than the start day.
DayOfWeek day = DateTime.Now.DayOfWeek;
DayOfWeek start_day = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), sr.start_day);
DayOfWeek end_day = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), sr.end_day);
if (end_day < start_day)
end_day += 7;
if (day < start_day)
day += 7;
if (day >= start_day && day <= end_day)
{
//Action
}
extention for DateTime
public static bool IsWeekend(this DateTime date)
{
return new[] {DayOfWeek.Sunday, DayOfWeek.Saturday}.Contains(date.DayOfWeek);
}
This is an elegant solution for the problem. It's a class that can easily be imported into other projects. The coding allows the programmer to dynamically assign what days to check for and pass them as a string array to the class. The data can come from a database or be hard coded when you pass it to an instance of this class for processing. It returns the values of True if you're off work and False if you're working that day. Below the class I provided a simple example of implementation. This class features: Dynamic allocation of what days you have off, Simple error handler by setting strings to lowercase before comparing them, Easily integrated with a database that has your work schedule where your days off may not always be the same. Easily integrated as a hard coded number of days off.
// The Class To Check If You're Off Work
class DayOffChecker
{
public bool CheckDays(List<string> DaysOff)
{
string CurrentDay = DateTime.Now.DayOfWeek.ToString();
CurrentDay.ToLower();
foreach (string DayCheck in DaysOff)
{
DayCheck.ToLower();
if (CurrentDay == DayCheck)
{
return (true);
}
}
return (false);
}
}
// Example usage code:
class Program
{
List<string> DaysOff = List<string>();
DaysOff.Add("Saturday"); // Add some values to our list.
DaysOff.Add("Sunday");
DayOffChecker CheckToday = new DayOffChecker();
if(CheckToday.CheckDays(DaysOff))
{
Console.WriteLine("You're Off Today!!!");
}
}
We can also follow similar approach of checking if a given hour is between two hours. Following is the algorithm
checkIfFallsInRange(index,start,end)
bool normalPattern = start <= end ;
if ( normalPattern)
return index>=start && index<=end;
else
return index>=start || index <=end;
My simple solution to determining if the current day is a workday or not is:
public static bool IsWorkDay(this DateTime dt)
{
return IsWorkDay(dt, DayOfWeek.Sunday, DayOfWeek.Saturday);
}
public static bool IsWorkDay(this DateTime dt, params DayOfWeek[] noneWorkDays)
{
return !noneWorkDays.Contains(dt.DayOfWeek);
}
It assumes Sunday / Saturday are non-work days. Otherwise the user can specify the non-work days. And is an extension for easy of use.
Note: To avoid a loop could created a bit flag.
DayOfWeek Day = DateTime.Today.DayOfWeek;
int Time = DateTime.Now.Hour;
if (Day != DayOfWeek.Saturday && Day != DayOfWeek.Sunday)
{
if (Time >= 8 && Time <= 16)
{
//It is Weekdays work hours from 8 AM to 4 PM
{
}
else
{
// It is Weekend
}
You can use the DayOfWeek enumeration in order to see if a date is Sunday or Saturday. http://msdn.microsoft.com/en-us/library/system.dayofweek.aspx I hope this can help.
The line below will return "Sunday"
string nameOfTheDay = DateTime.Now.ToString("dddd", new System.Globalization.CultureInfo("en-GB")).ToLower();
if(nameOfTheDay != "sunday" && nameOfTheDay != "saturday")
{
//Do Stuff
}
public bool IsWeekend(DateTime dateToCheck)
{
DayOfWeek day = (DayOfWeek) dateToCheck.Day;
return ((day == DayOfWeek.Saturday) || (day == DayOfWeek.Sunday));
}
This question already has answers here:
Wanted: DateTime.TryNew(year, month, day) or DateTime.IsValidDate(year, month, day)
(2 answers)
Closed 4 years ago.
I am creating date using following code
try
{
newdatetime = new DateTime(2012, 2, 30);
break;
}
catch (ArgumentOutOfRangeException)
{
// Try 29 Feb if not 28.
}
The catch block is to catch the invalid date like 30 Feb. Is there any way to verify if the date is valid by speciying the parameters like (year, month, day)?
Well, with months you know the valid range so you can constrain that manually. Years are obviously not constrained in the normal sense, but are instead limited by the amount that DateTime can actually hold (0001 to 9999).
With days, there is the DaysInMonth(int year, int month) method that can tell you the maximum days for the provided month. This also gives you the leap year.
With this information, you can create your own method to check the range based on the provided integers.
Something like:
public static bool AreValidDateValues(int year, int month, int day)
{
if (month < 1 || month > 12)
return false;
if (year < DateTime.MinValue.Year || year > DateTime.MaxValue.Year)
return false;
var days = DateTime.DaysInMonth(year, month);
if (day < 1 || day > days)
return false;
return true;
}
Or if you can't be bothered with that, convert the raw values into a string representation of a date and put that into DateTime.TryParse, which will give a true/false for the provided string - just be careful with culture-sensitive parsing.
You can use DateTime.TryParse to perform the check :
DateTime d;
var isValid = DateTime.TryParse(String.Format("{0}/{1}/{2}", 2, 31, 2012), out d);
Console.WriteLine(isValid);
I would like to know a simple algorithm to check if the given instance of datetime lies between another two instances in C#.
Note:
I skimmed though this How do I check if a given datetime object is "between" two datetimes? and it was for python and many more for php. Most of the other questions were regarding difference between the two.
Details:
I am more specific about the time, date does not matter to me. For example i got DataBase entry for a staff who works between 10:00 Am - 9:00 Pm and I would like to know which staff is engaged in class at the given time like 2:00 Pm. Now this would return me the staff's details who are engaged at this time.
Edit
After accepting the answer(been more than year back), i realized i had incorrectly described the problem. But all i think that was to be done back then was to do date and time comparison. So answers by both Jason and VikciaR work.
DateTime.Ticks will account for the time. Use .Ticks on the DateTime to convert your dates into longs. Then just use a simple if stmt to see if your target date falls between.
// Assuming you know d2 > d1
if (targetDt.Ticks > d1.Ticks && targetDt.Ticks < d2.Ticks)
{
// targetDt is in between d1 and d2
}
Do simple compare > and <.
if (dateB < dateA && dateA < dateC)
//do something
If you care only on time:
if (dateA.TimeOfDay>dateB.TimeOfDay && dateA.TimeOfDay<dateC.TimeOfDay)
//do something
Write yourself a Helper function:
public static bool IsBewteenTwoDates(this DateTime dt, DateTime start, DateTime end)
{
return dt >= start && dt <= end;
}
Then call:
.IsBewteenTwoDates(DateTime.Today ,new DateTime(,,));
You can, use:
if (date >= startDate && date<= EndDate) { return true; }
You can use:
if ((DateTime.Compare(dateToCompare, dateIn) == 1) && (DateTime.Compare(dateToCompare, dateOut) == 1)
{
//do code here
}
or
if ((dateToCompare.CompareTo(dateIn) == 1) && (dateToCompare.CompareTo(dateOut) == 1))
{
//do code here
}