I'm trying to make a C# method to fulfill this user story.
These are the 2 acceptance criteria
Start time must be at least one hour later than the current system time.
End time must be at last one hour after start time.
Both of the start and end time must be DateTime values, so I can parse it with the TryParse method.
Here's what I have in my code so far:
`
private DateTime datetime;
public DateTime datetimeStart { get; set; }
public DateTime datetimeEnd { get; set; }
while (true) {
Util.GetInput("Delivery window start (dd/mm/yyyy hh:mm)");
string userInput = ReadLine();
if(DateTime.TryParse(userInput, out datetime))
{
if (datetime.TimeOfDay.Hours - DateTime.Now.TimeOfDay.Hours >= 1) {
datetimeStart = datetime;
}
break;
}
else
{
WriteLine("\tDelivery window start must be at least one hour in the future.");
}
}
while (true) {
Util.GetInput("Delivery window end (dd/mm/yyyy hh:mm)");
string userInput = ReadLine();
if(DateTime.TryParse(userInput, out datetime))
{
if (datetime.TimeOfDay.Hours - datetimeStart.TimeOfDay.Hours >= 1) {
datetimeEnd = datetime;
}
break;
}
else
{
WriteLine("\tDelivery window end must be at least one hour later than the start.");
}
}
`
I'm not fully sure how the DateTime type works yet, but later on, I'd need to get an output string with this format:
"The pickup window for your order will be 04:00 on 30/10/2022 and 20:00 on 30/10/2022", and just replace the data in the string with values from datetimeStart and datetimeEnd
DateTime provides all the tools to write your conditions in straightforward code:
one hour later than / after checkTime
is just
checkTime.AddHours(1)
and
someTime must be at least one hour later than / after checkTime
becomes
someTime >= checkTime.AddHours(1)
So your code may look something like this:
...........................
if (datetime >= DateTime.Now.AddHours(1)) {
datetimeStart = datetime;
}
...........................
if (datetime >= datetimeStart.AddHours(1)) {
datetimeEnd = datetime;
}
...........................
A general rule of thumb is that any internal time keeping should be done in UTC, but when presenting in a UI (form or console) that you may show in local time.
Another rule is that when comparing DateTime objects that they should have the same Kind.
Perhaps add something like:
DateTime earliestStartTime = DateTime.UtcNow.AddHours(1);
Later if you have a variable named startTime you want to make sure that it is greater than or equal to earliestStartTime. Once you have startTime set, you can then have:
DateTime earliestEndTime = startTime.AddHours(1);
and likewise compare endTime to earliestStartTime for validity.
When presenting times to the user, you can use the .ToLocalTime() method.
Related
I have a property in my clas:
public string Starttime
This is a input value from the client side. Now I want this value to compare with the time of the computer.
Pseudo code:
if(inputvalue startime = time on the computer){
//do something
}
else{
thread.sleep(100)
}
The syntax of the time must not be Datetime but only the time like 13:00, 13:00, 14:57 etc.
Which datatype is best to achieve this requirement?
You can consider using a TimeSpan to keep just the hours and minutes and you'll be good.
Alternatively, you can get the entire date and only compare the TimeOfDay property:
var endTime = DateTime.Now;
if(startTime.Hour == endTime.Hour && startTime.Minute == startTime.Minute)
{
// Do what you do when they are equal...
}
else
{
// They are not equal. Which is more likely.
}
Also, I'd advise using a DateTime object as opposed to a string for that.
Update
Another way to cater for the slight differences if you have a tolerance is as follows:
var endTime = DateTime.Now; // Here I am assuming a tolerance of 2 seconds.
if(endTime.Subtract(startTime).Seconds <= 2)
{
// Basically the same.
}
else
{
// Different as far as we are concerned.
}
You can use the TimeSpan type to represent hours and minutes. It has a Parse method that will take your input string and convert it to a TimeSpan. Then you can compare the time with the current time, using DateTime.Now.TimeOfDay:
static void Main(string[] args)
{
var clientInput = "14:57";
var startTime = TimeSpan.Parse(clientInput);
var currentTime = DateTime.Now.TimeOfDay;
Console.WriteLine("The start time is: {0}", startTime.ToString("hh\\:mm"));
Console.WriteLine("The current time is: {0}", currentTime.ToString("hh\\:mm"));
var difference = currentTime.Subtract(startTime);
if ((int)difference.TotalMinutes == 0)
{
Console.WriteLine("It's time to start!");
}
else if ((int)difference.TotalMinutes > 0)
{
Console.WriteLine("We should have started {0} minutes ago!",
(int)difference.TotalMinutes);
}
else
{
Console.WriteLine("We will start in: {0} hours and {1} minutes.",
-difference.Hours, -difference.Minutes);
}
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output
You can use TimeSpan as the datatype. Here is the MSDN reference with all the methods and properties that you should have access to:
https://msdn.microsoft.com/en-us/library/system.timespan(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.timespan(v=vs.90).aspx
Hope this can help you out.
I have a view model in which I am storing a DateTime but in my view using a JQUERY datetimepicker, time only:
ViewModel
[DataType(DataType.Time)]
public DateTime? MondayFrom { get; set; }
[DataType(DataType.Time)]
public DateTime? MondayTo { get; set; }
As it stands, when the Create method gets called it is using todays date plus the time selected from the timepicker.
As I am not particularly concerned with the Date part of the DateTime, I want to change the day, month & year to 01/01/1900 or something less specific than the date the record was written, before the record is created, this is purely to avoid any confusion in the future.
I don't want to get bogged down on whether this is the right thing to do or not.
I'm struggling to get a handle on the Date part of the DateTime, see below:
public void CreateClub(Club club)
{
foreach (var item in club.MeetingDays)
{
// change Date part to 01/01/1900, leave the time as is..
}
_repository.CreateClub(club);
}
How might I floor the date part of the item but leave the time well alone?
Just use the TimeOfDay property to extract the time within the day, and add that to the date you want:
private static readonly DateTime BaseDate = new DateTime(1900, 1, 1);
var updatedDateTime = BaseDate + otherDateTime.TimeOfDay;
You could even write an extension method or two:
public static DateTime WithDate(this DateTime start, DateTime date)
{
// No need to use the Date property if you already know
// it will be midnight...
return date.Date + start.TimeOfDay;
}
public static DateTime WithFloorDate(this DateTime start)
{
return start.WithDate(FloorDate);
}
Of course, I'd suggest you use Noda Time where you can specify dates, times and date/time values (with or without a time zone or UTC offset0 separately, but that's a different conversation.
DateTime is immutable - you cant just change part of it. You can extract the time and add it to a "base" date:
for(int i=0; i < club.MeetingDays.Count; i++)
{
club.MeetingDays[i] = new DateTime(1900, 1, 1) + club.MeetingDays[i].TimeOfDay;
}
Note that you need a for loop so you can place the new value back in the collection. You could also use Linq:
club.MeetingDays = club.MeetingDays
.Select(t => new DateTime(1900, 1, 1) + t.TimeOfDay)
.ToList();
Assuming that club.MeetingDays is a List<Datetime>
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 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...
}
I have database where data is stored along timestamp entries, that are keys.
i need a function that can transform a date like DateTime.Now into a timestamp interval representing, for today as example, Aug 30th 00:00:00h to Aug 30th 23:59:59h.
How could i write that function?
What i want is to do something like
select all from table where timestamp is between a and b.(those and b values would represent the initial and terminal timestamps for a day.)
I did not create the db, i cannot modify it, i can only query it.
This will return a tuple representing the interval you probably want:
Tuple<DateTime,DateTime> GetDateInterval(DateTime datetime) {
var start = datetime.Date;
var end = start.AddDays(1).AddTicks(-1);
return new Tuple<DateTime, DateTime>(start, end);
}
Usage:
var interval = GetDateInterval(DateTime.Now);
Console.WriteLine(interval.Item1);
Console.WriteLine(interval.Item2);
Output:
30.08.2011 0:00:00
30.08.2011 23:59:59
Maybe DateTime.Now.TimeOfDay.Ticks is what you are looking for.
Hard to tell what you want, but here is a way to get the interval:
var start = DateTime.Today;
var end = start.AddDays(1).AddSeconds(-1);
It's hard to answer how you should store the values in the DB since you haven't provided enough details about the table layout.
If you have the scope of a day, you can calculate the ticks withing the day:
// ----------------------------------------------------------------------
public long GetTicksOfDay( DateTime moment )
{
return moment.Subtract( moment.Date ).Ticks;
} // GetTicksOfDay
I think what you need is a TimeSpan.
You can just substract one DateTime from another, and the result will be a TimeSpan of the difference.
I guess you might try using a structure as a TimeInterval:
public struct TimeInterval
{
private readonly DateTime _startTime;
private readonly DateTime _endTime;
public DateTime StartTime { get { return _startTime; } }
public DateTime EndTime { get { return _endTime; } }
public TimeInterval(DateTime now)
{
_startTime = now.Date;
_endTime = now.Date.AddDays(1).AddTicks(-1);
}
}
You can call it:
TimeInterval day = new TimeInterval(DateTime.Now);
I'm writing a service but I want to have config settings to make sure that the service does not run within a certain time window on one day of the week. eg Mondays between 17:00 and 19:00.
Is it possible to create a datetime that represents any monday so I can have one App config key for DontProcessStartTime and one for DontProcessEndTime with a values like "Monday 17:00" and "Monday 19:00"?
Otherwise I assume I'll have to have separate keys for the day and time for start and end of the time window.
Any thoughts?
thanks
You could use a utility that will parse your weekday text into a System.DayOfWeek enumeration, example here. You can then use the Enum in a comparison against the DateTime.Now.DayOfWeek
You can save the day of the week and start hour and endhour in your config file, and then use a function similar to the following:
public bool ShouldRun(DateTime dateToCheck)
{
//These should be read from your config file:
var day = DayOfWeek.Monday;
var start = 17;
var end = 19;
return !dateToCheck.DayOfWeek == day &&
!(dateToCheck.Hour >= start && dateToCheck.Hour < end);
}
You can use DayOfTheWeek property of the DateTime.
And to check proper time you can use DateTime.Today (returns date-time set to today with time set to 00:00:00) and add to it necessary amount of hours and minutes.
The DateTime object cannot handle a value that means all mondays. It would have to be a specific Monday. There is a DayOfWeek enumeration. Another object that may help you is a TimeSpan object. You could use the DayOfWeek combined with TimeSpan to tell you when to start, then use another TimeSpan to tell you how long
This is very rough code, but illustrates that you can check a DateTime object containing the current time as you wish to do:
protected bool IsOkToRunNow()
{
bool result = false;
DateTime currentTime = DateTime.Now;
if (currentTime.DayOfWeek != DayOfWeek.Monday && (currentTime.Hour <= 17 || currentTime.Hour >= 19))
{
result = true;
}
return result;
}