Calculate time between 9:00 AM -- 6:00 PM - c#

I'm having a string with 8:00 AM. Suppose I want to check that time 8:00 AM comes before 9:00 Am -- 6:00 PM.
How to check this or if time 11:00 AM comes in between time 9:00 AM -- 6:00 PM?
How to find it out in c#?

You can use the DateTime object, its static parse method, and comparison operators.
Something like the following:
newTime = DateTime.Parse("8:00 AM");
fixedTime = DateTime.Parse("11:00 AM");
if (newTime < fixedTime)
{
// do something
}
If needed, you can subtract one DateTime from another to get a TimeSpan - that is a duration.

String s = "8:00 AM";
DateTime dt = DateTime.Parse(s);
if (dt < DateTime.Parse("9:00 AM"))
{
Console.WriteLine("Before");
}
else if (dt <= DateTime.Parse("6:00 PM"))
{
Console.WriteLine("Between");
}
else
{
Console.WriteLine("After");
}

The general method would be to convert the time to a number that you can then use to compare.
So 8:00 AM would be simply 8, 6:00 PM would be 18, therefore 18 > 8 etc.

The function DateTime.Parse() can be used to turn strings into "DateTime" objects.
You have your start time: 9:00AM.
You have your end time: 6:00PM.
You therefore have your distance between the two:
6:00PM - 9:00AM.
That will give you a TimeSpan object.
Then you take your 'mystery time', and do:
X:XX - 9:00AM.
If the resulting timespan is > 0 AND the resulting timespan is < 6:00PM-9:00AM tiemspan, you're good.
Alternately, you can simply do
if (myTime > 9:00AM && myTime < 6:00PM)

DateTime beginDate = DateTime.Today.AddHours(9);
DateTime endDate = DateTime.Today.AddHours(18);
TimeSpan diff = endDate - beginDate;
Now diff contains difference between begin date and end date.

what about
int _dateTimeCompare = DateTime.Compare(DateTime1, DateTime2);
and then _dateTimeCompare < 1 = DateTime 1 is less than DateTime2, 0 = they're the same, > 0 = DateTime2 > DateTime1
So you can then do the comparisons.
A simple is _myDate between _date1 and _date2 would then be:
if (DateTime.Compare(_myDate, _date1) >= 0 && DateTime.Compare(_myDate, _date2) <= 0)
{
// we're between _date1 and _date2
}
kinda thing :)

I don't see the problem casting the strings to DateTime variables (as they should be) and then using the Compare method to perform the comparison.
Additionally, the DateTime structure implements operators such as >, <, >=, <= which simplify comparisons.

You can try to parse your string into a TimeSpan object using TimeSpan.Parse or TimeSpan.TeyParse.
If the parse succeeds, you'll have a TimeSpan object that can be compared to other timespan objects using the standard comparison operators. You can also carry out operations such as addition and substraction to calculate time between two timespans or to calculate a new time based on a time and duration.
Timespan is a very nice little class, please do not reinvent the wheel.
Update
As remarked by Cerebrus in the comment, TimeSpan is kind of weird in the sense that it can represent both a point in time and a duration. (The DateTime.TimeOfDay property is a Timespan even though it is a point in time).
It is perhaps a better idea to create DateTime objects with a default date part and use this as the basis of calculations. The intent of the code will be clearer.
Operations such as comparisons, additions and substractions are also available on DateTimes and yield DateTimes or TimeSpan where applicable.

Related

Change the time forward

I am getting dates from the database and for each date I want to change the time forward starting from the DateTime that was obtained from the database until I get to a given Fixed Time (Y). However, (Y) might be in the next day.
For example if the date from the database is [7/6/2017 5:00:00 AM] and the given Fixed Time is 10:00 PM then I want to get [7/6/2017 10:00:00 PM].
However if the fixed time is 02:00 AM then I want to get [7/7/2017 02:00:00 AM] (notice that the date has increased by one)
Note: The code is running, but I modified the code to make it shorter and make more sense. Thus, there might be syntax or spelling mistakes.
My first solution was something like this:
private DateTime setTimeForeward(DateTime date) {
DateTime today = DateTime.ParseExact(FixedTime, "hh:mm tt", CultureInfo.InvariantCulture);
TimeSpan difference = today.TimeOfDay - date.TimeOfDay;
return date + difference;
}
That didn't work as expected when the fixed time is 02:00 AM. The difference becomes negative( it doesn't go around the clock) and the date will be [7/6/2017 02:00:00 AM].
I ended up with the following code
private DateTime setTimeForeward(DateTime date) {
DateTime today = DateTime.ParseExact(FixedTime "hh:mm tt", CultureInfo.InvariantCulture);
TimeSpan difference = today.TimeOfDay - date.TimeOfDay;
if (difference.Hours < 0) {
difference += new TimeSpan(24, 0, 0);
}
return date + difference;
}
I am not sure if my function is logically correct and I feel like I am overthinking it. Also,I am not sure if there's a better way or a built in function that does what I want for me. Basically, I am looking for a correct and an elegant solution.
Thank you very much in advanced.
In this method, I'm using DateTime fixedTime to represent a time. I don't really care about it's Day, Month, and Year values.
static DateTime GetClosingTime(DateTime fixedTime, DateTime dbTime)
{
var cutoff = new DateTime(dbTime.Year, dbTime.Month, dbTime.Day, fixedTime.Hour, fixedTime.Minute, fixedTime.Second);
if (dbTime < cutoff)
return cutoff;
else
{
cutoff = cutoff.AddDays(1);
return cutoff;
}
}
Here's calling it with your provided example input.
var FixedTime10PM = new DateTime(1, 1, 1, 22, 0, 0);
var FixedTime02AM = new DateTime(1, 1, 1, 2, 0, 0);
var dbTime = new DateTime(2018, 6, 20, 5, 0, 0);
var dt1 = GetClosingTime(FixedTime10PM, dbTime);
var dt2 = GetClosingTime(FixedTime02AM, dbTime);
Console.WriteLine(dt1.ToLongDateString() + " " + dt1.ToLongTimeString());
Console.WriteLine(dt2.ToLongDateString() + " " + dt2.ToLongTimeString());
And here's my output:
EDIT:
Simplified method based on suggestions in comments:
static DateTime GetClosingTime(DateTime fixedTime, DateTime dbTime)
{
var cutoff = new DateTime(dbTime.Year, dbTime.Month, dbTime.Day, fixedTime.Hour, fixedTime.Minute, fixedTime.Second);
return dbTime < cutoff ? cutoff : cutoff.AddDays(1);
}
Your logic is almost right but you shouldn't be checking for difference.Hours because there might be a difference in minutes (or even seconds if you changed the format later).
I adjusted your function and changed some variable names to make them easier to follow:
private DateTime SetTimeForward(DateTime originalDate)
{
TimeSpan newTime = DateTime.ParseExact(FixedTime,
"hh:mm tt",
CultureInfo.InvariantCulture).TimeOfDay;
TimeSpan diff = newTime - originalDate.TimeOfDay;
if (diff.Ticks < 0)
diff = diff.Add(new TimeSpan(24, 0, 0));
return originalDate.Add(diff);
}
Some remarks:
If your FixedTime is really fixed, you might want to store it directly as a TimeSpan so you don't have to parse it every time.
If you parse the FixedTime because it's changeable, you might pass it as a second argument instead:
private DateTime SetTimeForward(DateTime originalDate, string fixedTime)
Or:
private DateTime SetTimeForward(DateTime originalDate, TimeSpan newTime)
The current implementation does not change the date value if the newTime is equal to originalDate.TimeOfDay. I.E., If the originalDate is 7/6/2017 2:00 AM and the FixedTime/newTime is 02:00 AM, the returned date will be equal to the originalDate. If that's not your desired behavior, you might change diff.Ticks < 0 to diff.Ticks <= 0.
Slightly different approach:
private DateTime setTimeForeward(DateTime date)
{
var targetTimeOfDay = TimeSpan.ParseExact(FixedTime, "hh:mm tt", CultureInfo.InvariantCulture);
if (targetTimeOfDay < date.TimeOfDay)
{
date = date.AddDays(1);
}
return date.Date + targetTimeOfDay;
}
I'm getting target time as TimeSpan from the beginning instead of creating DateTime and getting TimeOfDay (which is TimeSpan).
Then I check if the target time of day is lower than time to be modified and if it is I add one day.
I use date.Date + targetTimeOfDay as return value as date.Date will return date with time set to 00:00 and adding target time to it will already set the target hour without calculating the difference.

compare two dates time hours and minutes (not secs)?

This is may be silly question. But I am missing logic here. I have to compare dates with date time with hours and minutes (not with seconds).
IF first field time is older then second field execute condition
right now I am doing if (Convert.ToDateTime(newItem["Modified"]) < Convert.ToDateTime(properties.ListItem["Modified"]))
example if("02/12/2015 11:58" < "02/12/2015 12:01") then execute condition.
You could create new DateTime objects with mostly the same values, but with seconds set to 0. Example:
DateTime date1WithoutSeconds = new DateTime(dt1.Year, dt1.Month, dt1.Day, dt1.Hour, dt1.Minute, 0);
DateTime date2WithoutSeconds = new DateTime(dt2.Year, dt2.Month, dt2.Day, dt2.Hour, dt2.Minute, 0);
bool b = date1WithoutSeconds < date2WithoutSeconds;
You could subtract the two dates, and if the TotalSeconds of the difference is less than 60 AND the minues are the same, then they are equal:
var first = Convert.ToDateTime(newItem["Modified"]);
var second = Convert.ToDateTime(properties.ListItem["Modified"]);
if (first.Subtract(second).TotalSeconds < 60 && first.Minute == second.Minute)
{
Console.WriteLine("They are equal");
}
You should use the DateTime.CompareTo method.
Grab and assign both dates as DateTime objects:
DateTime date = Convert.ToDateTime(newItem["Modified"]);
DateTime compareDate = Convert.ToDateTime(properties.ListItem["Modified"]);
You can now use the CompareTo method of the DateTime object to see if the instance is earlier, the same, or later than the other, returning -1, 0, and 1 respectively.
So, following your example: if("02/12/2015 11:58" < "02/12/2015 12:01"), first date being date and second being compareDate, the code:
date.CompareTo(compareDate);
will return -1, telling you the instance invoking the method is earlier than the object you are comparing it to.
Here is the MSDN.
One more way that should work.
DateTime date1 = Convert.ToDateTime(newItem["Modified"]);
DateTime date2 = Convert.ToDateTime(properties.ListItem["Modified"]));
if( date1.AddSeconds(-date1.Second) < date2.AddSeconds(-date2.Second) ) {
}
But, I would wonder...is it really that you need to ignore the seconds and "floor" the result so that 12:59:00 is the same as 12:59:59 but different than 12:58:59 even though there's only a second of difference...or do you need to know that it's greater than a minute of difference? If you really just want to make sure that it is a minute apart, use TimeSpan (date1 - date2).TotalSeconds > 60
I doubt this is likely, but if your DateTime is a string WITH milliseconds, then do:
if( date1.AddSeconds(-date1.Second).AddMilliseconds(-date1.Millisecond) <
date2.AddSeconds(-date2.Second).AddMilliseconds(-date2.Millisecond) )
{
}
First of all, the sample data you've mentioned in your question doesn't include seconds, so by default Convert.ToDateTime will assign '00' as seconds, so it would compare without the seconds.
But let's say that you do provide seconds in the actual data. You can use the following:
var date1 = Convert.ToDateTime(newItem["Modified"]);
var date2 = Convert.ToDateTime(properties.ListItem["Modified"]);
if (date1.AddSeconds(-date1.Second) < date2.AddSeconds(-date2.Second))

How to set current time to a value

I was just wondering if there is a way to get the current time and set it into a value.
If its 12:06 AM.. I want to get that time and set it into currentTime.
Example
float currentTime = 0;
currentTime = 12.06;
As others have mentioned, the DateTime class would be ideal for this, and to work out the difference between 2 date/times:
DateTime end = DateTime.Now;
DateTime start = new DateTime(2011, 12, 5, 12, 6,0);
double hours = (end - start).TotalHours;
The subtraction of DateTime objects results in a TimeSpan object that you can use to see the hours/minutes etc.
try DateTime class
DateTime dt = DateTime.Now;
Is this what you're looking for?
DateTime currentTime;
currentTime = DateTime.Now;
Don't use floats or strings. You can do all kinds of cool things using DateTime.
Here's how you'd get the hours that someone worked:
var clockIn = new DateTime(2011,12,4,9,0,0); // December 4th, 9 AM
var clockOut = new DateTime(2011,12,4,17,0,0); // December 4th, 5 PM
var duration = clockOut - clockIn; // TimeSpan
Console.Write(duration.TotalHours); // 8
A few people have mentioned how, but as a 'better' recommendation you should use
DateTime currentTime = DateTime.UtcNow
Otherwise you have issues when the clocks go back, if your timing code is run on those days. (plus it is far easier to alter the UTC time to local time than it is to convert a '1am' to UTC (as there will be two of them when the clocks go back)
Well if you really what it as a float then try:
var currentDate = DateTime.Now;
float currentTime = float.Parse((currentDate.Hour > 12 ? currentDate.Hour -12 :
currentDate.Hour) + "." + currentDate.Minute);
I wouldn't recommend comparing dates or time with floats. A better options would be to use timespans.
You should be using a Timespan instance for time related values, you can use the flexibility to get the required values like
TimeSpan ts = DateTime.Now.TimeOfDay;
ts.ToString("hh:mm") // this could be what you are looking for
You could then use ts.TotalHours which would give you fractional hours (as a double) else you could construct a string specifically using ts.Hours ..ts.Minutes play around and it could be prove useful.
Try the following:
DateTime StartTime=StartTime value;
DateTime CurrentTime=DateTime.Now;
TimeSpan dt = CurrentTime.Subtract(StartTime);
In dt you will get a working time period.
If you want to have the difference between two times, then do this:
DateTime dateOne = DateTime.Parse(enteredTime);
DateTime dateTwo = DateTime.Now;
TimeSpan difference = dateOne - dateTwo;

How to Handle Actual Time with Durations in C#?

What's the preferred approach to compare a complete DateTime instance with an hour, minute, and second which represents an actual time of day, with the ability to operate over those triplets (eg add hours, minutes seconds..)?
My current approach is something like
DateTime startHour = new DateTime(1900,1,1,12,25,43);
DateTime endHour = new DateTime(1900,1,1,13,45,32);
// I need to, say, know if a complete DateTime instance
// is later than startHour plus 15 minutes
DateTime now = DateTime.Now();
startHour = startHour.addMinutes(15);
if (now.CompareTo(new DateTime(now.Year, now.Month, now.Day, startHour.Hour,
startHour.Minute, startHour.Second)) > 0)
{
//I can do something now
}
This is very cumbersome and even failure prone. TimeSpans are not a solution as far as I can see, because they represent spans and aren't bound by the 24 hours limit (a TimeSpan of 56 hours 34 minutes is valid.)
What's the preferred approach for this type of calculations?
It's not at all clear what you mean by "is greater than startHour"... but taking
TimeSpan startHour = new TimeSpan(12, 25, 43);
if (endHour.TimeOfDay > startHour)
{
...
}
... works pretty simply.
By all means add argument checking to make sure that you don't specify a value for startHour which is < 0 or > 23 hours, but that's all pretty easy.
.NET's date and time API is quite primitive (even in 3.5) compared with, say, Joda Time - but in this particular case I think it's not too bad.
A little hint - .NET supports arithmetic operations on DateTime objects, and returns a TimeSpan object. Thus, you can do the following:
DateTime fromDate = ....
DateTime toDate = ....
TimeSpan diff = toDate - fromDate;
and you can expand this to:
DateTime fromDate = DateTime.Now;
DateTime toDate = DateTime.Now.addMinutes(x);
if ((toDate - fromDate).TotalMinutes > 15) {
...
}
You should use TimeSpan for startHour and endHour.
When comparing with now, you should "convert" them to a full DateTime or get the Time with DateTime.TimeOfDay as mentioned by Jon Skeet.
TimeSpan startHour = new TimeSpan(12, 25, 43);
DateTime now = DateTime.Now;
if (now.CompareTo(DateTime.Today.Add(startHour)) > 0) {
//...
}
or
TimeSpan startHour = new TimeSpan(12, 25, 43);
DateTime now = DateTime.Now;
if (now.TimeOfDay.CompareTo(startHour) > 0) {
//...
}
So you're only interested in the time component of the date.
if(DateTime.Now.TimeOfDay > startHour.TimeOfDay)
{
// do stuff
}
What's wrong with doing this?

DateTime of next 3am occurrence

I'm sure this is very easy, but I've got a sudden mental block.
I'm trying to get a DateTime object for the next occurence of 3am. For example, if DateTime.Now is 16/july/2009 : 12:04pm - the next occurance of 3am would be 17/july/2009 : 03:00
However, if DateTime.Now was 17/july/2009 : 01:00 then the next occurence would still be 17/july/2009 : 03:00 (not the day after).
Does that make sense?
One option:
DateTime now = DateTime.Now;
DateTime today3am = now.Date.AddHours(3);
DateTime next3am = now <= today3am ? today3am : today3am.AddDays(1);
Another:
DateTime now = DateTime.Now;
DateTime today = now.Date;
DateTime next3am = today.AddHours(3).AddDays(now.Hour >= 3 ? 1 : 0)
Lots of ways of skinning that particular cat :)
This is all in local time of course, which means you don't need to worry about time zones. Life becomes trickier if you want to get time zones involved...
Note that it's a good idea to take DateTime.Now once to avoid problems if the date rolls over while you're calculating...
DateTime now = DateTime.Now;
DateTime threeAM = now.Date.AddHours(3);
if (threeAM < now)
threeAM = threeAM.AddDays(1);
//just add 24 - 3 = 21 hours and get Today (start of day) and Add 3 hour
DateTime now = DateTime.Now.AddHours(21).Today.AddHours(3);
An alternative (using a function):
DateTime NextAt(TimeSpan time)
{
DateTime now = DateTime.Now;
DateTime result = now.Date + time;
return (now <= result) ? result : result.AddDays(1);
}
call it like:
DateTime next3am = NextAt(new TimeSpan(3,0,0));
You can do it without an if statement (or conditional operator):
// get the current time
DateTime now = DateTime.Now;
// get a 3:00 AM point in time in the future
DateTime next = now.Date.AddHours(24 + 3);
// subtract the number of whole extra days
next = next.AddDays((now - next).Days);
I always explain that you should get the point in time (DateTime.Now) only once in a calculation like this, as it's a changing value, so do I have to repeat it? Well, I just did. ;)
I think this One:
DateTime.Now.Date.AddHours(3).AddMinutes(0).AddSeconds(0).AddDays(1);

Categories

Resources