How to find the valid time if StartTime and EndTime is given? - c#

How can the method be implemented in C#?
string StartTime = "06:10 PM";
string Endtime = "08:10 PM";
DateTime current_time = DateTime.Now;
bool validTime = validTimeFindout(StartTime,Endtime,current_time);
bool validTimeFindout(string StartTime, string Endtime,DateTime current_time){
// This method should return true
// when the current_time>= StartTime && current_time<=Endtime
// otherwise false
}
I tried to find out the valid time in the specific range and for that validTimeFindout method will help and here the method is comparing the time get from local pc and compare them with StartTime and Endtime

Starting with .NET 6, you can use the TimeOnly Struct:
static bool IsTimeBetween(string startTime, string endTime, DateTime dateTime)
{
if (TimeOnly.TryParse(startTime, out var t1) &&
TimeOnly.TryParse(endTime, out var t2))
{
return TimeOnly.FromDateTime(dateTime).IsBetween(t1, t2);
}
return false;
}
Note that TimeOnly.IsBetween supports time ranges that span midnight such as 23:00-01:00.

You can use DateTime.TryParse() method to parse a string into the DateTime datatype.
DateTime datatypes can be compared as numeric datatypes with <, <=, ==, !=, >=, >
bool validTimeFindout(string StartTime, string Endtime, DateTime current_time){
DateTime start;
DateTime.TryParse(StartTime, out start);
DateTime end;
DateTime.TryParse(Endtime, out end);
return current_time >= start && current_time <= end;
}

You just need to convert the inputs from string to datetime and do the calculations: datetime.parse()
bool validTimeFindout(string StartTime, string Endtime, DateTime current_time)
{
DateTime _startTime = DateTime.Parse(StartTime);
DateTime _endTime = DateTime.Parse(Endtime);
if (current_time >= _startTime && current_time <= _endTime)
return true;
else
return false;
}

First you need to convert those strings to DateTime objects.
Then you should compare those DateTime objects and current time.
using System.Globalization;
string StartTime = "06:10 PM";
string Endtime = "08:10 PM";
DateTime current_time = DateTime.Now;
try {
bool validTime = validTimeFindout(StartTime, Endtime, current_time);
Console.WriteLine(validTime);
}catch(Exception exc) {
Console.WriteLine(exc.Message);
}
bool validTimeFindout(string StartTime, string Endtime, DateTime current_time) {
DateTime start = ParseTimeString(StartTime);
DateTime end = ParseTimeString(Endtime);
if(current_time.CompareTo(start) >= 0 && current_time.CompareTo(end) <= 0) {
return true;
} else {
return false;
}
}
DateTime ParseTimeString(string timeString) {
string format = "hh:mm tt";
DateTime result;
if (DateTime.TryParseExact(timeString, format, CultureInfo.GetCultureInfo("en-US"), DateTimeStyles.None, out result)) {
return result;
} else {
throw new Exception("Cannot parse time!");
}
}
There are also several things you can rethink and fix.
Naming pattern - IMHO is valid is not a good name for method checking if a DateTime is between other DateTimes.
Use single naming convention and stick to it. The most popular convention in C# is cammel case (like startTime).
Is it really needed to store those DateTimes in strings formatted like "01:10 PM"? Why doesn't you simply store DateTime objects?

Related

Check if less than 7 days before ending [duplicate]

I see that this question has been answered for Java, JavaScript, and PHP, but not C#. So, how might one calculate the number of days between two dates in C#?
Assuming StartDate and EndDate are of type DateTime:
(EndDate - StartDate).TotalDays
The top answer is correct, however if you would like only WHOLE days as an int and are happy to forgo the time component of the date then consider:
(EndDate.Date - StartDate.Date).Days
Again assuming StartDate and EndDate are of type DateTime.
Use TimeSpan object which is the result of date substraction:
DateTime d1;
DateTime d2;
return (d1 - d2).TotalDays;
I think this will do what you want:
DateTime d1 = DateTime.Now;
DateTime d2 = DateTime.Now.AddDays(-1);
TimeSpan t = d1 - d2;
double NrOfDays = t.TotalDays;
DateTime xmas = new DateTime(2009, 12, 25);
double daysUntilChristmas = xmas.Subtract(DateTime.Today).TotalDays;
// Difference in days, hours, and minutes.
TimeSpan ts = EndDate - StartDate;
// Difference in days.
int differenceInDays = ts.Days; // This is in int
double differenceInDays= ts.TotalDays; // This is in double
// Difference in Hours.
int differenceInHours = ts.Hours; // This is in int
double differenceInHours= ts.TotalHours; // This is in double
// Difference in Minutes.
int differenceInMinutes = ts.Minutes; // This is in int
double differenceInMinutes= ts.TotalMinutes; // This is in double
You can also get the difference in seconds, milliseconds and ticks.
In case someone wants numer of whole days as a double (a, b of type DateTime):
(a.Date - b.Date).TotalDays
There often is a debate on time (hours) when it comes to counting days between two dates. The responses to the question and their comments show no exception.
Considering StartDate and EndDate are of type DateTime: if performance is not a concern, I would strongly recommend documenting your calculation through intermediate conversions. For example, (EndDate - StartDate).Days is unintuitive because rounding will depend on the hour component of StartDate and EndDate.
If you want the duration in days to include fractions of days, then as already suggested
use (EndDate - StartDate).TotalDays.
If you want the duration to reflect
the distance between two days, then use (EndDate.Date - StartDate.Date).Days
If you want the duration to reflect the
duration between the morning of the start date, and the evening of
the end date (what you typically see in project management software), then use
(EndDate.Date - StartDate.Date).Days + 1
You can try this
EndDate.Date.Subtract(DateTime.Now.Date).Days
Using a timespan would solve the problems as it has many attributes:
DateTime strt_date = DateTime.Now;
DateTime end_date = Convert.ToDateTime("10/1/2017 23:59:59");
//DateTime add_days = end_date.AddDays(1);
TimeSpan nod = (end_date - strt_date);
Console.WriteLine(strt_date + "" + end_date + "" + "" + nod.TotalHours + "");
Console.ReadKey();
For a and b as two DateTime types:
DateTime d = DateTime.Now;
DateTime c = DateTime.Now;
c = d.AddDays(145);
string cc;
Console.WriteLine(d);
Console.WriteLine(c);
var t = (c - d).Days;
Console.WriteLine(t);
cc = Console.ReadLine();
For beginners like me that will stumble upon this tiny problem, in a simple line, with sample conversion to int:
int totalDays = Convert.ToInt32((DateTime.UtcNow.Date - myDateTime.Date).TotalDays);
This calculates the total days from today (DateTime.UtcNow.Date) to a desired date (myDateTime.Date).
If myDateTime is yesterday, or older date than today, this will give a positive (+) integer result.
On the other side, if the myDateTime is tomorrow or on the future date, this will give a negative (-) integer result due to rules of addition.
Happy coding! ^_^
First declare a class that will return later:
public void date()
{
Datetime startdate;
Datetime enddate;
Timespan remaindate;
startdate = DateTime.Parse(txtstartdate.Text).Date;
enddate = DateTime.Parse(txtenddate.Text).Date;
remaindate = enddate - startdate;
if (remaindate != null)
{
lblmsg.Text = "you have left with " + remaindate.TotalDays + "days.";
}
else
{
lblmsg.Text = "correct your code again.";
}
}
protected void btncal_Click(object sender, EventArgs e)
{
date();
}
Use a button control to call the above class. Here is an example:
You can use the code below:
int DateDifInSecond = EndDate.Subtract(StartDate).TotalSeconds
Get the difference between the two dates and then get the days from:
int total_days = (EndDate - StartDate).TotalDays
try this truly worked Get actual days diff. date format is "dd/MM/yyyy"
string[] d1 = txtFromDate.Values.Split('/');
string[] d2 = txtToDate.Values.Split('/');
DateTime FrmDt = new DateTime(Convert.ToInt32(d1[2]), Convert.ToInt32(d1[1]), Convert.ToInt32(d1[0]));
DateTime ToDt = new DateTime(Convert.ToInt32(d2[2]), Convert.ToInt32(d2[1]), Convert.ToInt32(d2[0]));
TimeSpan TDiff = ToDt.Subtract(FrmDt);
String DaysDiff = TDiff.TotalDays.ToString();
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
DateTime d = Calendar1.SelectedDate;
// int a;
TextBox2.Text = d.ToShortDateString();
string s = Convert.ToDateTime(TextBox2.Text).ToShortDateString();
string s1 = Convert.ToDateTime(Label7.Text).ToShortDateString();
DateTime dt = Convert.ToDateTime(s).Date;
DateTime dt1 = Convert.ToDateTime(s1).Date;
if (dt <= dt1)
{
Response.Write("<script>alert(' Not a valid Date to extend warranty')</script>");
}
else
{
string diff = dt.Subtract(dt1).ToString();
Response.Write(diff);
Label18.Text = diff;
Session["diff"] = Label18.Text;
}
}

Net Core 2 StartOfWeek [duplicate]

How do I find the start of the week (both Sunday and Monday) knowing just the current time in C#?
Something like:
DateTime.Now.StartWeek(Monday);
Use an extension method:
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(-1 * diff).Date;
}
}
Which can be used as follows:
DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Monday);
DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
The quickest way I can come up with is:
var sunday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);
If you would like any other day of the week to be your start date, all you need to do is add the DayOfWeek value to the end
var monday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Monday);
var tuesday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Tuesday);
A little more verbose and culture-aware:
System.Globalization.CultureInfo ci =
System.Threading.Thread.CurrentThread.CurrentCulture;
DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
DayOfWeek today = DateTime.Now.DayOfWeek;
DateTime sow = DateTime.Now.AddDays(-(today - fdow)).Date;
Using Fluent DateTime:
var monday = DateTime.Now.Previous(DayOfWeek.Monday);
var sunday = DateTime.Now.Previous(DayOfWeek.Sunday);
Ugly but it at least gives the right dates back
With start of week set by system:
public static DateTime FirstDateInWeek(this DateTime dt)
{
while (dt.DayOfWeek != System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
dt = dt.AddDays(-1);
return dt;
}
Without:
public static DateTime FirstDateInWeek(this DateTime dt, DayOfWeek weekStartDay)
{
while (dt.DayOfWeek != weekStartDay)
dt = dt.AddDays(-1);
return dt;
}
Let's combine the culture-safe answer and the extension method answer:
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
return DateTime.Today.AddDays(-(DateTime.Today.DayOfWeek- fdow));
}
}
This would give you the preceding Sunday (I think):
DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek, 0, 0, 0);
For Monday
DateTime startAtMonday = DateTime.Now.AddDays(DayOfWeek.Monday - DateTime.Now.DayOfWeek);
For Sunday
DateTime startAtSunday = DateTime.Now.AddDays(DayOfWeek.Sunday- DateTime.Now.DayOfWeek);
This may be a bit of a hack, but you can cast the .DayOfWeek property to an int (it's an enum and since its not had its underlying data type changed it defaults to int) and use that to determine the previous start of the week.
It appears the week specified in the DayOfWeek enum starts on Sunday, so if we subtract 1 from this value that'll be equal to how many days the Monday is before the current date. We also need to map the Sunday (0) to equal 7 so given 1 - 7 = -6 the Sunday will map to the previous Monday:-
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
dayOfWeek = dayOfWeek == 0 ? 7 : dayOfWeek;
DateTime startOfWeek = now.AddDays(1 - (int)now.DayOfWeek);
The code for the previous Sunday is simpler as we don't have to make this adjustment:-
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
DateTime startOfWeek = now.AddDays(-(int)now.DayOfWeek);
using System;
using System.Globalization;
namespace MySpace
{
public static class DateTimeExtention
{
// ToDo: Need to provide culturaly neutral versions.
public static DateTime GetStartOfWeek(this DateTime dt)
{
DateTime ndt = dt.Subtract(TimeSpan.FromDays((int)dt.DayOfWeek));
return new DateTime(ndt.Year, ndt.Month, ndt.Day, 0, 0, 0, 0);
}
public static DateTime GetEndOfWeek(this DateTime dt)
{
DateTime ndt = dt.GetStartOfWeek().AddDays(6);
return new DateTime(ndt.Year, ndt.Month, ndt.Day, 23, 59, 59, 999);
}
public static DateTime GetStartOfWeek(this DateTime dt, int year, int week)
{
DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
return dayInWeek.GetStartOfWeek();
}
public static DateTime GetEndOfWeek(this DateTime dt, int year, int week)
{
DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
return dayInWeek.GetEndOfWeek();
}
}
}
Putting it all together, with Globalization and allowing for specifying the first day of the week as part of the call we have
public static DateTime StartOfWeek ( this DateTime dt, DayOfWeek? firstDayOfWeek )
{
DayOfWeek fdow;
if ( firstDayOfWeek.HasValue )
{
fdow = firstDayOfWeek.Value;
}
else
{
System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
fdow = ci.DateTimeFormat.FirstDayOfWeek;
}
int diff = dt.DayOfWeek - fdow;
if ( diff < 0 )
{
diff += 7;
}
return dt.AddDays( -1 * diff ).Date;
}
Step 1:
Create a static class
public static class TIMEE
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(-1 * diff).Date;
}
public static DateTime EndOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = (7 - (dt.DayOfWeek - startOfWeek)) % 7;
return dt.AddDays(1 * diff).Date;
}
}
Step 2: Use this class to get both start and end day of the week
DateTime dt = TIMEE.StartOfWeek(DateTime.Now ,DayOfWeek.Monday);
DateTime dt1 = TIMEE.EndOfWeek(DateTime.Now, DayOfWeek.Sunday);
var now = System.DateTime.Now;
var result = now.AddDays(-((now.DayOfWeek - System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek + 7) % 7)).Date;
This would give you midnight on the first Sunday of the week:
DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek, t.Hour, t.Minute, t.Second);
This gives you the first Monday at midnight:
DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek - 1, t.Hour, t.Minute, t.Second);
Try with this in C#. With this code you can get both the first date and last date of a given week. Here Sunday is the first day and Saturday is the last day, but you can set both days according to your culture.
DateTime firstDate = GetFirstDateOfWeek(DateTime.Parse("05/09/2012").Date, DayOfWeek.Sunday);
DateTime lastDate = GetLastDateOfWeek(DateTime.Parse("05/09/2012").Date, DayOfWeek.Saturday);
public static DateTime GetFirstDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
DateTime firstDayInWeek = dayInWeek.Date;
while (firstDayInWeek.DayOfWeek != firstDay)
firstDayInWeek = firstDayInWeek.AddDays(-1);
return firstDayInWeek;
}
public static DateTime GetLastDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
DateTime lastDayInWeek = dayInWeek.Date;
while (lastDayInWeek.DayOfWeek != firstDay)
lastDayInWeek = lastDayInWeek.AddDays(1);
return lastDayInWeek;
}
I tried several, but I did not solve the issue with a week starting on a Monday, resulting in giving me the coming Monday on a Sunday. So I modified it a bit and got it working with this code:
int delta = DayOfWeek.Monday - DateTime.Now.DayOfWeek;
DateTime monday = DateTime.Now.AddDays(delta == 1 ? -6 : delta);
return monday;
The same for end of the week (in style of Compile This's answer):
public static DateTime EndOfWeek(this DateTime dt)
{
int diff = 7 - (int)dt.DayOfWeek;
diff = diff == 7 ? 0 : diff;
DateTime eow = dt.AddDays(diff).Date;
return new DateTime(eow.Year, eow.Month, eow.Day, 23, 59, 59, 999) { };
}
Thanks for the examples. I needed to always use the "CurrentCulture" first day of the week and for an array I needed to know the exact Daynumber.. so here are my first extensions:
public static class DateTimeExtensions
{
//http://stackoverflow.com/questions/38039/how-can-i-get-the-datetime-for-the-start-of-the-week
//http://stackoverflow.com/questions/1788508/calculate-date-with-monday-as-dayofweek1
public static DateTime StartOfWeek(this DateTime dt)
{
//difference in days
int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.
//As a result we need to have day 0,1,2,3,4,5,6
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-1 * diff).Date;
}
public static int DayNoOfWeek(this DateTime dt)
{
//difference in days
int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.
//As a result we need to have day 0,1,2,3,4,5,6
if (diff < 0)
{
diff += 7;
}
return diff + 1; //Make it 1..7
}
}
Here is a correct solution. The following code works regardless if the first day of the week is a Monday or a Sunday or something else.
public static class DateTimeExtension
{
public static DateTime GetFirstDayOfThisWeek(this DateTime d)
{
CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
var first = (int)ci.DateTimeFormat.FirstDayOfWeek;
var current = (int)d.DayOfWeek;
var result = first <= current ?
d.AddDays(-1 * (current - first)) :
d.AddDays(first - current - 7);
return result;
}
}
class Program
{
static void Main()
{
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine("Current culture set to en-US");
RunTests();
Console.WriteLine();
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("da-DK");
Console.WriteLine("Current culture set to da-DK");
RunTests();
Console.ReadLine();
}
static void RunTests()
{
Console.WriteLine("Today {1}: {0}", DateTime.Today.Date.GetFirstDayOfThisWeek(), DateTime.Today.Date.ToString("yyyy-MM-dd"));
Console.WriteLine("Saturday 2013-03-02: {0}", new DateTime(2013, 3, 2).GetFirstDayOfThisWeek());
Console.WriteLine("Sunday 2013-03-03: {0}", new DateTime(2013, 3, 3).GetFirstDayOfThisWeek());
Console.WriteLine("Monday 2013-03-04: {0}", new DateTime(2013, 3, 4).GetFirstDayOfThisWeek());
}
}
Modulo in C# works bad for -1 mod 7 (it should be 6, but C# returns -1)
so... a "one-liner" solution to this will look like this :)
private static DateTime GetFirstDayOfWeek(DateTime date)
{
return date.AddDays(
-(((int)date.DayOfWeek - 1) -
(int)Math.Floor((double)((int)date.DayOfWeek - 1) / 7) * 7));
}
I did it for Monday, but with similar logic for Sunday.
public static DateTime GetStartOfWeekDate()
{
// Get today's date
DateTime today = DateTime.Today;
// Get the value for today. DayOfWeek is an enum with 0 being Sunday, 1 Monday, etc
var todayDayOfWeek = (int)today.DayOfWeek;
var dateStartOfWeek = today;
// If today is not Monday, then get the date for Monday
if (todayDayOfWeek != 1)
{
// How many days to get back to Monday from today
var daysToStartOfWeek = (todayDayOfWeek - 1);
// Subtract from today's date the number of days to get to Monday
dateStartOfWeek = today.AddDays(-daysToStartOfWeek);
}
return dateStartOfWeek;
}
The following method should return the DateTime that you want. Pass in true for Sunday being the first day of the week, false for Monday:
private DateTime getStartOfWeek(bool useSunday)
{
DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
if(!useSunday)
dayOfWeek--;
if(dayOfWeek < 0)
{// day of week is Sunday and we want to use Monday as the start of the week
// Sunday is now the seventh day of the week
dayOfWeek = 6;
}
return now.AddDays(-1 * (double)dayOfWeek);
}
You could use the excellent Umbrella library:
using nVentive.Umbrella.Extensions.Calendar;
DateTime beginning = DateTime.Now.BeginningOfWeek();
However, they do seem to have stored Monday as the first day of the week (see the property nVentive.Umbrella.Extensions.Calendar.DefaultDateTimeCalendarExtensions.WeekBeginsOn), so that previous localized solution is a bit better. Unfortunate.
Edit: looking closer at the question, it looks like Umbrella might actually work for that too:
// Or DateTime.Now.PreviousDay(DayOfWeek.Monday)
DateTime monday = DateTime.Now.PreviousMonday();
DateTime sunday = DateTime.Now.PreviousSunday();
Although it's worth noting that if you ask for the previous Monday on a Monday, it'll give you seven days back. But this is also true if you use BeginningOfWeek, which seems like a bug :(.
Following on from Compile This' answer, use the following method to obtain the date for any day of the week:
public static DateTime GetDayOfWeek(DateTime dateTime, DayOfWeek dayOfWeek)
{
var monday = dateTime.Date.AddDays((7 + (dateTime.DayOfWeek - DayOfWeek.Monday) % 7) * -1);
var diff = dayOfWeek - DayOfWeek.Monday;
if (diff == -1)
{
diff = 6;
}
return monday.AddDays(diff);
}
This will return both the beginning of the week and the end of the week dates:
private string[] GetWeekRange(DateTime dateToCheck)
{
string[] result = new string[2];
TimeSpan duration = new TimeSpan(0, 0, 0, 0); //One day
DateTime dateRangeBegin = dateToCheck;
DateTime dateRangeEnd = DateTime.Today.Add(duration);
dateRangeBegin = dateToCheck.AddDays(-(int)dateToCheck.DayOfWeek);
dateRangeEnd = dateToCheck.AddDays(6 - (int)dateToCheck.DayOfWeek);
result[0] = dateRangeBegin.Date.ToString();
result[1] = dateRangeEnd.Date.ToString();
return result;
}
I have posted the complete code for calculating the begin/end of week, month, quarter and year on my blog
ZamirsBlog
Calculating this way lets you choose which day of the week indicates the start of a new week (in the example I chose Monday).
Note that doing this calculation for a day that is a Monday will give the current Monday and not the previous one.
//Replace with whatever input date you want
DateTime inputDate = DateTime.Now;
//For this example, weeks start on Monday
int startOfWeek = (int)DayOfWeek.Monday;
//Calculate the number of days it has been since the start of the week
int daysSinceStartOfWeek = ((int)inputDate.DayOfWeek + 7 - startOfWeek) % 7;
DateTime previousStartOfWeek = inputDate.AddDays(-daysSinceStartOfWeek);
I work with a lot of schools, so correctly using Monday as the first day of the week is important here.
A lot of the most terse answers here don't work on Sunday -- we often end up returning the date of tomorrow on Sunday, which is not good for running a report on last week's activities.
Here's my solution, which returns last Monday on Sunday, and today on Monday.
// Adding 7 so remainder is always positive; Otherwise % returns -1 on Sunday.
var daysToSubtract = (7 + (int)today.DayOfWeek - (int)DayOfWeek.Monday) % 7;
var monday = today
.AddDays(-daysToSubtract)
.Date;
Remember to use a method parameter for "today" so it's unit testable!!
Here is a combination of a few of the answers. It uses an extension method that allows the culture to be passed in. If one is not passed in, the current culture is used. This will give it maximum flexibility and reuse.
/// <summary>
/// Gets the date of the first day of the week for the date.
/// </summary>
/// <param name="date">The date to be used</param>
/// <param name="cultureInfo">If none is provided, the current culture is used</param>
/// <returns>The date of the beggining of the week based on the culture specifed</returns>
public static DateTime StartOfWeek(this DateTime date, CultureInfo cultureInfo=null) =>
date.AddDays(-1 * (7 + (date.DayOfWeek - (cultureInfo ?? CultureInfo.CurrentCulture).DateTimeFormat.FirstDayOfWeek)) % 7).Date;
Example Usage:
public static void TestFirstDayOfWeekExtension() {
DateTime date = DateTime.Now;
foreach(System.Globalization.CultureInfo culture in CultureInfo.GetCultures(CultureTypes.UserCustomCulture | CultureTypes.SpecificCultures)) {
Console.WriteLine($"{culture.EnglishName}: {date.ToShortDateString()} First Day of week: {date.StartOfWeek(culture).ToShortDateString()}");
}
}
If you want Saturday or Sunday or any day of week, but not exceeding the current week (Sat-Sun), I got you covered with this piece of code.
public static DateTime GetDateInCurrentWeek(this DateTime date, DayOfWeek day)
{
var temp = date;
var limit = (int)date.DayOfWeek;
var returnDate = DateTime.MinValue;
if (date.DayOfWeek == day)
return date;
for (int i = limit; i < 6; i++)
{
temp = temp.AddDays(1);
if (day == temp.DayOfWeek)
{
returnDate = temp;
break;
}
}
if (returnDate == DateTime.MinValue)
{
for (int i = limit; i > -1; i++)
{
date = date.AddDays(-1);
if (day == date.DayOfWeek)
{
returnDate = date;
break;
}
}
}
return returnDate;
}
We like one-liners: Get the difference between the current culture's first day of week and the current day, and then subtract the number of days from the current day:
var weekStartDate = DateTime.Now.AddDays(-((int)now.DayOfWeek - (int)DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek));

DateTime in C# where the precision is represented

I have a scenario where I need to parse strings representing datetimes.
The length of the string implies the precision:
"2012-11-11" represents any moment in "november 11 of 2012"
"2012-11" represents any moment in "november of 2012"
"2012-11-11 10:11" represents any seconds in that minute
I would need to parse these strings as ranges of time.
Is there a datastructure that can help representing this or do I need to parse it manually and use 2 DateTimes.
You will have to write your own class to manage this.
Let's assume that your date strings are always in one of the following formats:
yyyy-M-d HH:mm:ss
yyyy-M-d HH:mm
yyyy-M-d HH
yyyy-M-d
yyyy-M
yyyy
Then you can write a class to encapsulate this as follows:
public sealed class TimeRange
{
public TimeRange(string dateTimeString)
{
DateTime dateTime;
if (DateTime.TryParseExact(dateTimeString, #"yyyy-M-d HH\:mm\:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddSeconds(1);
}
else if (DateTime.TryParseExact(dateTimeString, #"yyyy-M-d HH\:mm", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddMinutes(1);
}
else if (DateTime.TryParseExact(dateTimeString, #"yyyy-M-d HH", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddHours(1);
}
else if (DateTime.TryParseExact(dateTimeString, #"yyyy-M-d", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddDays(1);
}
else if (DateTime.TryParseExact(dateTimeString, #"yyyy-M", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddMonths(1);
}
else if (DateTime.TryParseExact(dateTimeString, #"yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
_start = dateTime;
_end = dateTime.AddYears(1);
}
else
{
throw new ArgumentException("date/time is invalid: " + dateTimeString, "dateTimeString");
}
}
public DateTime Start
{
get
{
return _start;
}
}
public DateTime ExclusiveEnd
{
get
{
return _end;
}
}
private readonly DateTime _start;
private readonly DateTime _end;
}
Note that for simplicity the end of the range, ExclusiveEnd, is expressed as an exclusive range. That means you'd make comparisons like:
if (timeRange.Start <= targetDateTime && targetDateTime < timeRange.ExclusiveEnd)
...
rather than the following, which would be incorrect:
if (timeRange.Start <= targetDateTime && targetDateTime <= timeRange.ExclusiveEnd)
...
Note the difference between < timeRange.ExclusiveEnd and <= timeRange.ExclusiveEnd
To avoid this subtlety you could add to the class a Contains(DateTime) method like:
public bool Contains(DateTime target)
{
return (_start <= target) && (target < _end);
}
A DateTime doesn't represent a period of time, it represents a specific moment in time.
You could use DateTime.TryParse() to parse the string however the interpretation of that is up to you.
https://msdn.microsoft.com/en-us/library/system.datetime.tryparse%28v=vs.110%29.aspx
Example
string foo = "11 August 2016";
DateTime bar = DateTime.Now;
DateTime.TryParse(foo, out bar);
Console.WriteLine(bar.ToString());
will output 11/08/2016 00:00:00
so you could assume this represents any time from 11/08/2016 to 11/08/2016 23:59:59 although it will miss out the case where the time specified was specifically 11/08/2016 00:00:00. Is this a likely input??
Could you gave a bit more info on why you need to interpret it this way?

Unable to parse Oracle timestamp in C#

I have timestamp of Oracle:
string timestamp = "23-JUN-14 09.39.04.000000000 AM";
I am not able to parse it into system date time object. I used:
CultureInfo provider = CultureInfo.InvariantCulture;
String format = "yy-MMM-dd hh:mm:ss:fffffff";
string timestamp = "10-DEC-07 10.32.47.797201123 AM";
{
var date = DateTime.ParseExact(timestamp, format, provider);
DateTime dateTime = DateTime.ParseExact(timestamp.ToString(), "dd-MMM-y HH:mm:ss", CultureInfo.InvariantCulture);
}
It is still passing error. It is working 7 f after m but not more than that. I used try Parse, try ParseExact - is there any way?
According to https://stackoverflow.com/a/23198962/328864, there is no way to skip parts of an exact pattern, so i guess you could do something like this:
CultureInfo provider = CultureInfo.InvariantCulture;
string timestamp = "10-DEC-07 10.32.47.797201123 AM";
String format = String.Format("yy-MMM-dd hh.mm.ss.fffffff{0} tt", timestamp.Substring(26,2));
DateTime date = DateTime.ParseExact(timestamp, format, provider);
Console.WriteLine(date);
Not very pretty though.
Once we started to use ODP.NET, we had to implement an extension like below:
public static T ConvertOracleValue<T>(this object value)
{
if (value != null)
{
Type typeOfValue = value.GetType();
if (typeOfValue.Namespace.Contains("Oracle.DataAccess"))
{
if (typeOfValue.Name.Equals("OracleTimeStamp"))
{
int tempInt = 0;
Oracle.DataAccess.Types.OracleTimeStamp ots = (Oracle.DataAccess.Types.OracleTimeStamp)value;
tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0;
DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt);
return ConvertHelper.ConvertValue<T>(ret);
}
if (typeOfValue.Name.Equals("OracleTimeStampLTZ"))
{
int tempInt = 0;
Oracle.DataAccess.Types.OracleTimeStampLTZ ots = (Oracle.DataAccess.Types.OracleTimeStampLTZ)value;
tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0;
DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt);
return ConvertHelper.ConvertValue<T>(ret);
}
if (typeOfValue.Name.Equals("OracleTimeStampTZ"))
{
int tempInt = 0;
Oracle.DataAccess.Types.OracleTimeStampTZ ots = (Oracle.DataAccess.Types.OracleTimeStampTZ)value;
tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0;
DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt);
return ConvertHelper.ConvertValue<T>(ret);
}
string temp = value.ToString();
return ConvertHelper.ConvertValue<T>(temp);
}
}
else
{
return default(T);
}
return ConvertHelper.ConvertValue<T>(value);
}
where ConvertHelper.ConvertValue is another extension:
public static class ConvertHelper
{
public static T ConvertValue<T>(object value)
{
Type typeOfT = typeof(T);
if (typeOfT.BaseType != null && typeOfT.BaseType.ToString() == "System.Enum")
{
return (T)Enum.Parse(typeOfT, Convert.ToString(value));
}
if ((value == null || value == Convert.DBNull) && (typeOfT.IsValueType))
{
return default(T);
}
if (value is IConvertible)
{
return (T)Convert.ChangeType(value, typeOfT, new CultureInfo("en-GB"));
}
return (T)Convert.ChangeType(value, typeOfT);
}
}
This worked like a charm in our test, integration and production environments.
.NET DateTime structure has a precision of tick - 100 nanoseconds - 0.0000001 of second - 7 decimal positions after the point.
Oracle TimeStamp has a precision of up to nanosecond - 0.000000001 - 9 decimal positions after the point.
That is why standard DateTime cannot store all possible oracle TimeStamps. And its parsing function simply fail on more precise string representations of TimeStamp.
So, what could be tried:
Format your TimeStamps in query to some format parseable by DataTime(with loss of precision if necessary) - http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm
Or create your own more precise CustomTimeStamp .Net structure and parse to it manually

Convert String value format of YYYYMMDDHHMMSS to C# DateTime

I have a need to convert a string value in the form "YYYYMMDDHHMMSS" to a DateTime. But not sure on how, may be a DateTime.Tryparse can be used to make this happen. Or is there any other way to do it. I can do this using some string operations to take "YYYYMMDD" alone, convert to a datetime and then add HH, MM, SS separately to that DateTime. But is there any DateTime.TryParse() methods that I can use in one line to convert a "YYYYMMDDHHMMSS" format string value to a DateTime value?
Define your own parse format string to use.
string formatString = "yyyyMMddHHmmss";
string sample = "20100611221912";
DateTime dt = DateTime.ParseExact(sample,formatString,null);
In case you got a datetime having milliseconds, use the following formatString
string format = "yyyyMMddHHmmssfff"
string dateTime = "20140123205803252";
DateTime.ParseExact(dateTime ,format,CultureInfo.InvariantCulture);
Thanks
You have to use a custom parsing string. I also suggest to include the invariant culture to identify that this format does not relate to any culture. Plus, it will prevent a warning in some code analysis tools.
var date = DateTime.ParseExact(value, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
class Program
{
static void Main(string[] args)
{
int transactionDate = 20201010;
int? transactionTime = 210000;
var agreementDate = DateTime.Today;
var previousDate = agreementDate.AddDays(-1);
var agreementHour = 22;
var agreementMinute = 0;
var agreementSecond = 0;
var startDate = new DateTime(previousDate.Year, previousDate.Month, previousDate.Day, agreementHour, agreementMinute, agreementSecond);
var endDate = new DateTime(agreementDate.Year, agreementDate.Month, agreementDate.Day, agreementHour, agreementMinute, agreementSecond);
DateTime selectedDate = Convert.ToDateTime(transactionDate.ToString().Substring(6, 2) + "/" + transactionDate.ToString().Substring(4, 2) + "/" + transactionDate.ToString().Substring(0, 4) + " " + string.Format("{0:00:00:00}", transactionTime));
Console.WriteLine("Selected Date : " + selectedDate.ToString());
Console.WriteLine("Start Date : " + startDate.ToString());
Console.WriteLine("End Date : " + endDate.ToString());
if (selectedDate > startDate && selectedDate <= endDate)
Console.WriteLine("Between two dates..");
else if (selectedDate <= startDate)
Console.WriteLine("Less than or equal to the start date!");
else if (selectedDate > endDate)
Console.WriteLine("Greater than end date!");
else
Console.WriteLine("Out of date ranges!");
}
}

Categories

Resources