To get Calculate Time Worked - c#

I currently build a system there is a part to manage Employee timein and timeout, i want to calculate this
***night shift (Must Work 8 Hr)***
startTime- 10.00 PM
endTime- 06.00 AM
So I want to calculate actually worked hours for that date (timein - timeout). What I have done is
TimeSpan duration = DateTime.Parse(endTime).Subtract(DateTime.Parse(startTime));
Output :16:00
What I want is 8:00
Eg 2
startTime- 10.00 PM
endTime- 05.00 AM
Out Put : 7:00
How can i done this?

You have to use date with time as well to exact hours between two times. As you would be having different dates in the time. Assume shift starts at 18 march, 2013 at 10:00PM and ends 19 march, 2013 5:00AM

Try to use Timespan like;
DateTime a = new DateTime(2008, 01, 02, 23, 30, 00);
DateTime b = new DateTime(2008, 01, 03, 06, 30, 00);
TimeSpan duration = b - a;
Console.WriteLine(duration);
Output will be
07:00:00
Here is a DEMO.
A TimeSpan object represents a time interval (duration of time or
elapsed time) that is measured as a positive or negative number of
days, hours, minutes, seconds, and fractions of a second.

Related

Insert time without the date into my database

I tried to insert into my MS Access database a specific format to see how just the "time" in my database behaves, but when I tried to show what I got the date also, but I want to insert just the time.
I tried to convert the datetime variable to specific format and insert that
DateTime starttime = Convert.ToDateTime(DateTime.Now.ToShortTimeString());
DateTime nstarttime = Convert.ToDateTime(starttime.ToString("HH:mm"));
06/04/2019 22:55:00 that what I got and I want just the time
without the date
Your main issue is, that in .Net the time part of a DateTime is not a DateTime but a TimeSpan:
DateTime dateTime = new DateTime(2019, 6, 4, 22, 55, 0);
TimeSpan timePart = dateTime.TimeOfDay;
In Access (VBA) however, a "time only" value is the time of the date of the VBA Date epoch which is 1899-12-30. Depending on how you insert the time in an Access table, you may have to apply the time part to the epoch to obtain a value like that Access would use:
DateTime dateTime = new DateTime(2019, 6, 4, 22, 55, 0);
TimeSpan timePart = dateTime.TimeOfDay;
DateTime vbaEpoch = new DateTime(1899, 12, 30);
DateTime vbaTime = vbaEpoch.AddTicks(timePart.Ticks);
Of course, when reading back the values, ignore the date part:
TimeSpan timeOfDay = vbaTime.TimeOfDay;
This has been answered so many times, but nevertheless here is the link to one of the discussions Link 1:
Please check also this Link 2 with may useful patterns
This detail is one of the actual examples provided on Link 1:
DateTime dt = DateTime.Parse("6/22/2009 07:00:00 AM");
dt.ToString("HH:mm"); // 07:00 // 24 hour clock // hour is always 2 digits
dt.ToString("hh:mm tt"); // 07:00 AM // 12 hour clock // hour is always 2 digits
dt.ToString("H:mm"); // 7:00 // 24 hour clock
dt.ToString("h:mm tt"); // 7:00 AM // 12 hour clock
Hope this helps!
Cheers and happy coding!

How to get time elapsed from starting date to an end date C# [duplicate]

This question already has answers here:
Showing Difference between two datetime values in hours
(8 answers)
Closed 5 years ago.
I'm trying to get the time elapsed from a starting date to an end date in C#
Assuming that my start date is "11/19/2017 05:50 P.M." and the end date is "11/19/2017 05:55 P.M." get the time elapsed, in this case was 5:00 minutes.
But also would like to get for example "5 days and 25 minutes" elapsed
any idea to do this?
TimeSpan span = (EndDateTime - StartDateTime);
String.Format("{0} days, {1} hours, {2} minutes, {3} seconds",
span.Days, span.Hours, span.Minutes, span.Seconds);
Do this. Just subtract the dates and call the method you want
DateTime Date1=new DateTime(2017, 11, 29, 5 + 12, 50, 0);
DateTime date2 = new DateTime(2017, 11, 29, 5 + 12, 55, 0);
var diff = (date2 - date1);
Then call the method you want from the resulting diff object;
double minutesDiff=diff.TotalMinutes;
int days=minutesDiff \(24*60);
int minLeft= minutesDiff %(24*60);
You can finish it from here

Why doesn't subtracting two local DateTime values appear to account for Daylight Saving Time?

I'm playing with some C# code to try to gain an understanding of how subtracting DateTime objects in C# works with respect to Daylight Saving Time.
Per Google and other sources, the Daylight Saving Time "spring ahead" event in the Eastern Standard Time zone in 2017 was at 2:00am on March 12. So, the first few hours of the day on that date were:
12:00am - 1:00am
1:00am - 2:00am
(There was no 2:00am - 3:00am hour due to the "spring ahead")
3:00am - 4:00am
So, if I were to calculate the time differential between 1:00am and 4:00am in that time zone on that date, I'd expect the result to be 2 hours.
However, the code I put together to try to simulate this problem is returning a 3 hour TimeSpan.
Code:
TimeZoneInfo easternStandardTime = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime oneAm = TimeZoneInfo.ConvertTime(new DateTime(2017, 03, 12, 01, 00, 00), easternStandardTime);
DateTime fourAm = TimeZoneInfo.ConvertTime(new DateTime(2017, 03, 12, 04, 00, 00), easternStandardTime);
TimeSpan difference = (fourAm - oneAm);
Console.WriteLine(oneAm);
Console.WriteLine(fourAm);
Console.WriteLine(TimeZoneInfo.Local.IsDaylightSavingTime(oneAm));
Console.WriteLine(TimeZoneInfo.Local.IsDaylightSavingTime(fourAm));
Console.WriteLine(difference);
On my PC, this generates:
2017-03-12 01:00:00.000 -5
2017-03-12 04:00:00.000 -4
False
True
03:00:00
All of that output is as expected -- except that final value of 3 hours, which as I noted above, I would expect to be 2 hours instead.
Obviously, my code isn't correctly simulating the situation that I have in mind. What is the flaw?
Observe:
// These are just plain unspecified DateTimes
DateTime dtOneAm = new DateTime(2017, 03, 12, 01, 00, 00);
DateTime dtFourAm = new DateTime(2017, 03, 12, 04, 00, 00);
// The difference is not going to do anything other than 4-1=3
TimeSpan difference1 = dtFourAm - dtOneAm;
// ... but we have a time zone to consider!
TimeZoneInfo eastern = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// Use that time zone to get DateTimeOffset values.
// The GetUtcOffset method has what we need.
DateTimeOffset dtoOneAmEastern = new DateTimeOffset(dtOneAm, eastern.GetUtcOffset(dtOneAm));
DateTimeOffset dtoFourAmEastern = new DateTimeOffset(dtFourAm, eastern.GetUtcOffset(dtFourAm));
// Subtracting these will take the offset into account!
// It essentially does this: [4-(-4)]-[1-(-5)] = 8-6 = 2
TimeSpan difference2 = dtoFourAmEastern - dtoOneAmEastern;
// Let's see the results
Console.WriteLine("dtOneAm: {0:o} (Kind: {1})", dtOneAm, dtOneAm.Kind);
Console.WriteLine("dtFourAm: {0:o} (Kind: {1})", dtFourAm, dtOneAm.Kind);
Console.WriteLine("difference1: {0}", difference1);
Console.WriteLine("dtoOneAmEastern: {0:o})", dtoOneAmEastern);
Console.WriteLine("dtoFourAmEastern: {0:o})", dtoFourAmEastern);
Console.WriteLine("difference2: {0}", difference2);
Results:
dtOneAm: 2017-03-12T01:00:00.0000000 (Kind: Unspecified)
dtFourAm: 2017-03-12T04:00:00.0000000 (Kind: Unspecified)
difference1: 03:00:00
dtoOneAmEastern: 2017-03-12T01:00:00.0000000-05:00)
dtoFourAmEastern: 2017-03-12T04:00:00.0000000-04:00)
difference2: 02:00:00
Note that DateTime carries a DateTimeKind in its Kind property, which is Unspecified by default. It doesn't belong to any particular time zone. DateTimeOffset doesn't have a kind, it has an Offset, which tells you how far that local time is offset from UTC. Neither of these give you the time zone. That is what TimeZoneInfo object is doing. See "time zone != offset" in the timezone tag wiki.
The part I think you are perhaps frustrated with, is that for several historical reasons, the DateTime object does not ever understand time zones when doing math, even when you might have DateTimeKind.Local. It could have been implemented to observe the transitions of the local time zone, but it was not done that way.
You also might be interested in Noda Time, which gives a very different API for date and time in .NET, in a much more sensible and purposeful way.
using NodaTime;
...
// Start with just the local values.
// They are local to *somewhere*, who knows where? We didn't say.
LocalDateTime ldtOneAm = new LocalDateTime(2017, 3, 12, 1, 0, 0);
LocalDateTime ldtFourAm = new LocalDateTime(2017, 3, 12, 4, 0, 0);
// The following won't compile, because LocalDateTime does not reference
// a linear time scale!
// Duration difference = ldtFourAm - ldtOneAm;
// We can get the 3 hour period, but what does that really tell us?
Period period = Period.Between(ldtOneAm, ldtFourAm, PeriodUnits.Hours);
// But now lets introduce a time zone
DateTimeZone eastern = DateTimeZoneProviders.Tzdb["America/New_York"];
// And apply the zone to our local values.
// We'll choose to be lenient about DST gaps & overlaps.
ZonedDateTime zdtOneAmEastern = ldtOneAm.InZoneLeniently(eastern);
ZonedDateTime zdtFourAmEastern = ldtFourAm.InZoneLeniently(eastern);
// Now we can get the difference as an exact elapsed amount of time
Duration difference = zdtFourAmEastern - zdtOneAmEastern;
// Dump the output
Console.WriteLine("ldtOneAm: {0}", ldtOneAm);
Console.WriteLine("ldtFourAm: {0}", ldtFourAm);
Console.WriteLine("period: {0}", period);
Console.WriteLine("zdtOneAmEastern: {0}", zdtOneAmEastern);
Console.WriteLine("zdtFourAmEastern: {0}", zdtFourAmEastern);
Console.WriteLine("difference: {0}", difference);
ldtOneAm: 3/12/2017 1:00:00 AM
ldtFourAm: 3/12/2017 4:00:00 AM
period: PT3H
zdtOneAmEastern: 2017-03-12T01:00:00 America/New_York (-05)
zdtFourAmEastern: 2017-03-12T04:00:00 America/New_York (-04)
difference: 0:02:00:00
We can see a period of three hours, but it doesn't really mean the same as the elapsed time. It just means the two local values are three hours apart in their position on a clock. NodaTime understands the difference between these concepts, while .Net's built-in types do not.
Some follow-up reading for you:
What's wrong with DateTime anyway?
More Fun with DateTime
The case against DateTime.Now
Five Common Daylight Saving Time Antipatterns of .NET Developers
Oh, and one other thing. Your code has this...
DateTime oneAm = TimeZoneInfo.ConvertTime(new DateTime(2017, 03, 12, 01, 00, 00), easternStandardTime);
Since the DateTime you create has unspecified kind, you are asking to convert from your computer's local time zone to Eastern time. If you happen to be not in Eastern time, your oneAm variable might not be 1 AM at all!
Ok, so I made some minor changes to your code. Not sure if this is what you are trying to achieve or not but this will give you what you want...
static void Main() {
TimeZoneInfo easternStandardTime = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
TimeZone timeZone = TimeZone.CurrentTimeZone;
DateTime oneAm = TimeZoneInfo.ConvertTime(new DateTime(2017, 03, 12, 01, 00, 00), easternStandardTime);
DateTime fourAm = TimeZoneInfo.ConvertTime(new DateTime(2017, 03, 12, 04, 00, 00), easternStandardTime);
DaylightTime time = timeZone.GetDaylightChanges(fourAm.Year);
TimeSpan difference = ((fourAm - time.Delta) - oneAm);
Console.WriteLine(oneAm);
Console.WriteLine(fourAm);
Console.WriteLine(TimeZoneInfo.Local.IsDaylightSavingTime(oneAm));
Console.WriteLine(TimeZoneInfo.Local.IsDaylightSavingTime(fourAm));
Console.WriteLine(difference);
Console.ReadLine();
}
So this is addressed in the MSDN documentation.
Basicaly, when subtracting one date from another you should be using DateTimeOffset.Subtract() and not arithmetic subtraction as you have here.
TimeSpan difference = fourAm.Subtract(oneAm);
Yields the expected 2 hour time difference.

How to find overlapping hours of a timerange and a date range?

I have a time range 11:00 PM to 5:00 AM. (night hours range)
I have date range for eg.,
2014-04-01 00:00:00 to 2014-04-02 23:59:59
Now I need to calculate how many night hours are present in the given date range.
For the above example it should return 11 hours 59 minutes 59 seconds
Explanation:
2014-04-01 00:00 AM to 2014-04-01 5:00 AM = 5 hours
2014-04-01 11:00 PM to 2014-04-02 5:00 AM = 6 hours
2014-04-02 11:00 PM to 2014-04-02 11:59:59 PM = 0 hour 59 minutes 59 seconds
one second approximation is okay.
If these are strings, you need to parse them to DateTime with DateTime.ParseExact method and then get difference them with - operator. This gets you a TimeSpan. I see your strings have different formats. You need to parse them matched format one by one.
After that, you can use TimeSpan properties like;
string s = "2014-04-01 00:00 AM";
var date = DateTime.ParseExact(s,
"yyyy-MM-dd HH:mm tt",
CultureInfo.InvariantCulture);
string s1 = "2014-04-01 5:00 AM";
var date1 = DateTime.ParseExact(s1,
"yyyy-MM-dd H:mm tt",
CultureInfo.InvariantCulture);
TimeSpan ts = date1 - date;
Console.WriteLine(string.Format(#"{0} hours {1} minutes {2} seconds",
ts.Hours, ts.Minutes, ts.Seconds));
Output will be;
5 hours 0 minutes 0 seconds
If they are already DateTime, just use - operator and use .Hours, .Minutes and .Seconds properties of TimeSpan structure.
There is a project called Calculating Business Hours which is calculate business hours between two DateTime. You can implement your own night shift hours based this project.
You can use the CalendarPeriodCollector of the Time Period Library for .NET:
// ----------------------------------------------------------------------
public void NightHours()
{
CalendarPeriodCollectorFilter filter = new CalendarPeriodCollectorFilter();
filter.CollectingHours.Add( new HourRange( 0, 5 ) ); // working hours
filter.CollectingHours.Add( new HourRange( 23, 24 ) ); // working hours
CalendarTimeRange testPeriod =
new CalendarTimeRange( new DateTime( 2014, 4, 1 ),
new DateTime( 2014, 4, 3 ) );
Console.WriteLine( "Calendar period collector of period: " + testPeriod );
CalendarPeriodCollector collector =
new CalendarPeriodCollector( filter, testPeriod );
collector.CollectHours();
Console.WriteLine( "Duration: " + new DateDiff( collector.Periods.TotalDuration ) );
} // NightHours

How can I convert a DateTime to the number of seconds since 1970?

I'm trying to convert a C# DateTime variable to Unix time, ie, the number of seconds since Jan 1st, 1970. It looks like a DateTime is actually implemented as the number of 'ticks' since Jan 1st, 0001.
My current thought is to subtract Jan 1st, 1970 from my DateTime like this:
TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0));
return span.TotalSeconds;
Is there a better way?
That's basically it. These are the methods I use to convert to and from Unix epoch time:
public static DateTime ConvertFromUnixTimestamp(double timestamp)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
return origin.AddSeconds(timestamp);
}
public static double ConvertToUnixTimestamp(DateTime date)
{
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
TimeSpan diff = date.ToUniversalTime() - origin;
return Math.Floor(diff.TotalSeconds);
}
Update: As of .Net Core 2.1 and .Net Standard 2.1 a DateTime equal to the Unix Epoch can be obtained from the static DateTime.UnixEpoch.
If the rest of your system is OK with DateTimeOffset instead of DateTime, there's a really convenient feature:
long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
The only thing I see is that it's supposed to be since Midnight Jan 1, 1970 UTC
TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
You probably want to use DateTime.UtcNow to avoid timezone issue
TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0));
I use year 2000 instead of Epoch Time in my calculus. Working with smaller numbers is easy to store and transport and is JSON friendly.
Year 2000 was at second 946684800 of epoch time.
Year 2000 was at second 63082281600 from 1-st of Jan 0001.
DateTime.UtcNow Ticks starts from 1-st of Jan 0001
Seconds from year 2000:
DateTime.UtcNow.Ticks/10000000-63082281600
Seconds from Unix Time:
DateTime.UtcNow.Ticks/10000000-946684800
For example year 2020 is:
var year2020 = (new DateTime()).AddYears(2019).Ticks; // Because DateTime starts already at year 1
637134336000000000 Ticks since 1-st of Jan 0001
63713433600 Seconds since 1-st of Jan 0001
1577836800 Seconds since Epoch Time
631152000 Seconds since year 2000
References:
Epoch Time converter: https://www.epochconverter.com
Year 1 converter: https://www.epochconverter.com/seconds-days-since-y0
That approach will be good if the date-time in question is in UTC, or represents local time in an area that has never observed daylight saving time. The DateTime difference routines do not take into account Daylight Saving Time, and consequently will regard midnight June 1 as being a multiple of 24 hours after midnight January 1. I'm unaware of anything in Windows that reports historical daylight-saving rules for the current locale, so I don't think there's any good way to correctly handle any time prior to the most recent daylight-saving rule change.
UTC:
long timeSince1970 = DateTimeOffset.Now.ToUnixTimeSeconds();
Local time:
long timeSince1970 = DateTime.Now.Ticks / 10000000 - 62135596800;
You can create a startTime and endTime of DateTime, then do endTime.Subtract(startTime). Then output your span.Seconds.
I think that should work.

Categories