So I'm working on a calendar-based application in C#, and I need to get the days of the week that an event is to repeat itself (for instance, every Monday/Friday).
I'm storing the events in XML, defined similarly as such:
<events>
<event startDate = "Insert Date Here" endDate = "Insert Date Here">Event Name</event>
</events>
How could I simply and reliably store and retrieve specific days of the week in this XML file?
If it helps, I'll be specifying the days of the week by a CheckBoxList, which I will be looping through to check for, well, checks.
You can use the following from this XML library
XElement a = new XElement("root");
a.Set("day", DayOfWeek.Thursday, true); // true = set as attribute of 'a'
DayOfWeek day = a.Get("day", DayOfWeek.Friday); // DayOfWeek.Friday is default
Console.WriteLine(day);
Output:
Thursday
Generated XML:
<root day="Thursday" />
It would be easiest to serialize the values as ints then use them with an enum in the C# code (0 = Sunday, 1 = Monday, ect). You could also use the words.
Then you can read them and use the built in enum values as listed in the docs in code to maintain readability. Which, by the way,
if cast to an integer, its value ranges from zero (which indicates
DayOfWeek.Sunday) to six (which indicates DayOfWeek.Saturday).
If you provide specifics on how you are reading the data from the xml into your C# app I can provide more specifics.
This seems like you're injecting fragility into your design. Suppose that your <event>'s day-of-week (DoW) and date disagree? What does your app do?
I think it's better to calculate the day of week based on that initial date:
var repeatingEvents = new List<DateTime>();
repeatingEvents.Add(new DateTime(2015, 4, 15));
for (var i = 1; i < 5; i++)
{
repeatingEvents.Add(repeatingEvents[0].AddDays(7*i));
}
This gives you 5 events on the same day of week without having to worry about what the actual DoW is.
If you're absolutely insistent on serializing DoW, look to DateTime: It already supports a DayOfWeek function, and has a DayOfWeek enum for your use.
Related
I have a range of 2 dates given by my business: "we would like to have all data from July and 6 previous months". I create two dates:
_range1.MaxDateTime = new DateTime(today. Year, 7, 31);
_range1.MinDateTime = rangeLastDate.AddMonths(-6).AddDays(1);
Because the system will always perform the calculation on last 6 months. Last date is also always end of month. I have no problem to get the last day of the month. C# has the feature EndOfMonth() for this. But when I do so I always get the last day at midnight. when I create the DateTime() myself I also get a date a midnight.
In my code I use Entity Framework with LinQ. (old EF, not Core yet)
_range1_ShippedQuantities = DbContext.Job_Dtl
.Where(j=> j.LastShipDate >= _range1.MinDateTime && j.LastShipDate <= _range1.MaxDateTime)
This is not correct because my last datetime is the 31 at midnight and not the first of next month at midnight. I should do
_range1_ShippedQuantities = DbContext.Job_Dtl
.Where(j=> j.LastShipDate.Date >= _range1.MinDateTime.Date && j.LastShipDate.Date <= _range1.MaxDateTime.Date)
Or I can also manipulate the dates do force the time at 23:59:59... what I don't like. I still miss 1 second. I can add 999 milliseconds but i will still tell you I miss one millisecond. I can also add one day in a temp variable and use this temp variable in my LinQ query... yes but I have the feeling there is something better. How do you deal with these ranges?
But LinQ does not allow this. LinQ for entities cannot recognize the date.
As several people have commented on your question, the simplest and most common way to solve this problem is to choose an exclusive end date rather than an inclusive one.
var minDateInclusive = rangeLastDate.AddMonths(-6).AddDays(1);
var maxDateExclusive = rangeLastDate.AddDays(1);
DbContext.Job_Dtl
.Where(j=> j.LastShipDate >= minDateInclusive
&& j.LastShipDate < maxDateExclusive);
I'm currently working on an app to add data to a SQL table.
One of the fields in the table is for financial month as YYYYMM (e.g. 201805 for August 2018). I need to set this automatically when the row is added as we can't rely on the users to input the correct format.
Is there any way to set DateTime to start the year on 1st April (first day of financial year), or am I going to have to code my way around the issue.
Thanks for all the answers, they did help me solve the problem.
I eventually went with a really simple solution that I probably should have thought of in the first place.
string period = DateTime.Now.AddMonths(-3).ToString("yyyyMM");
What you want is a varchar (or nvarchar) column, with a default that looks something like:
(format(dateadd(month,(-4),getdate()),''yyyyMM'',''en-US''))
But, it appears that SQL Server doesn't like having a default with three functions nested inside each other (two, it seems ok with, but it burps on three). Instead, you can have a Date type column with a default of:
(dateadd(month,(-4),getdate()))
That seems to work, but it's a date 4 months ago. Then just format it correctly whenever you display it.
You could use the following piece of code to get the start of your desired financial year.
var year = DateTime.Now.Year;
DateTime firstDay;
if(DateTime.Now.Month <= 4)
firstDay = new DateTime(year-1, 4, 1);
else
firstDay = new DateTime(year, 4, 1);
There doesn't seem to be a way to do this automatically, but it looks simple enough.
We've been trying to figure out how to compare two calendar dates in C# ASP.NET.
The problem we have is that when a customer uses the calendar, they can choose to set it back in time.
Example:
2015-09-23 to 2015-08-23 <- this is something we don't want, it is set back in time.
How do we check if the start date is later than the end date.
We have seen someone using CDate? Which we did not understand how to use this.
We have tried to just remove the "-" from a string, convert it to an int and then calculate if the answer is less than 0.
But this was a big workaround. Is there an official or better way to do this?
If any more information is needed, feel free to ask!
You can use the CompareValidator in ASP.Net
<asp:CompareValidator ID="myID" ControlToCompare="StartDate"
ControlToValidate="EndDate" Type="Date" Operator="GreaterThanEqual"
ErrorMessage="The dates are not correct." runat="server"></asp:CompareValidator>
or else
DateTime d1 = new DateTime(2015, 9, 1);
DateTime d2 = new DateTime(2015, 8, 2);
if (d1 < d2)
{
//error
}
Easy enough. I assume its only the date part you are interested in and not the time. The DateTime.CompareTo() method compares two dates and returns one of the following integer values:
-1 Less Than
0 Equal To
1 Greater Than
Using this and the Current Date we can easily tell if the given date is in the past. This method will take a date string, like the one provide in your example, and compare it to the current date (ignoring the time element) and return true if the given date is in the past, or false if it is equal to or greater than the current date.
private bool IsDateInThePast(string inputDate)
{
DateTime dt = DateTime.Parse(inputDate);
return dt.CompareTo(DateTime.Parse(DateTime.Now.ToShortDateString())) < 0;
}
Obviously, you might want to add some validation and/or exception handling to handle an invalid input string.
i want to set the date to 1st of Jan 16 years ago from today's date. I used the code
DateTime dtm = new DateTime(DateTime.Today.Year, 1, 1);
dtm.AddYears(-16);
dtpDOB.Value = dtm;// assign value to date time picker
but it shows the date value as 1/1/2014, why this does not set the year part back in 16 years?
thanks
dtm = dtm.AddYears(-16);
Just assign the value
According to the MSDN documentation, .AddYears will return a new DateTime object rather than modifying the existing instance. So change your line to
dtm = dtm.AddYears(-16);
The DateTime type is a struct. Because of that, its properties are immutable (they can't be changed post-constructor). structs are passed by value in C#.
Because of that, as a few other people have said, you need to reassign the value.
dtm = dtm.AddYears(-16);
It's just like a typical string operation in C#. When you call string.Replace(string, string), you need to capture the return value of the operation. The same is true for LINQ-y IEnumerable<T> operations.
Although that said, it seems like you'd be better off to just call the constructor appropriately.
dtpDOB.Value = new DateTime(DateTime.Today.Year - 16, 1, 1);
I have a function which convert date to my formatdate and compare it to CurrentDate.
It worked well when I test it with date is a date in Octorber compare to today (16/10/2013)
But if date is a date in November, the value return is true which means date < currentdate. I dont know why, anyone can explain it to me ? Thanks so much.
function IsPast(date) {
var fullDate = new Date();
var twoDigitMonth = fullDate.getMonth() + 1 + "";
if (twoDigitMonth.length == 1) twoDigitMonth = "0" + twoDigitMonth;
var twoDigitDate = fullDate.getDate() + "";
if (twoDigitDate.length == 1) twoDigitDate = "0" + twoDigitDate;
var currentDate = twoDigitDate + "/" + twoDigitMonth + "/" + fullDate.getFullYear();
var startDate = $.fullCalendar.formatDate(date, 'dd/MM/yyyy');
if (startDate <= currentDate) {return true;}
return false;
}
If you are being passed a Date object (and that seems to be what you get), then you can simply do:
function isPast(date) {
return new Date() > date;
}
If date isn't a date object, convert it to one first.
Note that identifiers starting with a capital letter are, by convention, reserved for constructors.
Edit: When I first read your question, I saw that you were using day first dates and jumped to my conclusion without really taking in your code. I've taken a closer look, and it appears my initial conclusion is just a red herring. The real problem is that you are taking two dates, converting them both to strings, and then trying to compare them. That's just silly - it will only tell you which string comes first alphabetically. Even sillier, is that for one of the dates you manually construct the string, but for the other one, you use a date formatting function. Why wouldn't you just use the date formatting function for both dates?
RobG's answer is correct and should be accepted.
When I see the date "01/11/2013", I read it as January 11, 2013, whereas you read it as 1 November, 2013. See the predicament the JavaScript engine is in when it tries to parse that date?*
When parsing JavaScript dates, I like to use year first dates, as these are unambiguous as far as I know. Everybody interprets "2013/11/01" as 2013 November 1. Including every JavaScript Date implementation I've seen.
Change your date format to be unambiguous.
*Frankly, I'm surprised you are seeing that behavior. I would expect that your system would be configured to expect day first dates and that the JavaScript engine would use those settings to properly parse the date. But, I'm not that surprised.