I am trying to get the affected hours between 2 datetime and all i found was a python solution.
For example 'start' is 09:30 and 'end' is 14:00 (same day). The values I'd like returned are
[9:00, 10:00, 11:00, 12:00, 13:00, 14:00]
Python get whole hour values between 2 datetime objects
I can't seem to find any equivalent to C#.
So you want a list of all hours between both dates? You can use this query:
TimeSpan ts = dt2 - dt1;
IEnumerable<int> hoursBetween = Enumerable.Range(0, (int)ts.TotalHours)
.Select(i => dt1.AddHours(i).Hour);
Sample dates:
DateTime dt1 = new DateTime(2013, 07, 08, 15, 50, 00);
DateTime dt2 = new DateTime(2013, 07, 10, 19, 30, 00);
TimeSpan ts = dt2 - dt1;
IEnumerable<int> hoursBetween = Enumerable.Range(0, (int)ts.TotalHours)
.Select(i => dt1.AddHours(i).Hour);
foreach (int hour in hoursBetween)
Console.WriteLine(hour);
Output:
15
16
17
18
19
20
21
22
23
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
The following will return the total hours between the 2 DateTime objects:
(datevalue1 - datevalue2).TotalHours
And for a custom behavior,such as displaying a list of hours, use a simple custom method on that Timespan created to get a list of hours in your desired format.
Code suggestion of the top of my head:
public List<String> GenerateHours(DateTime t1,DateTime t2){
if ((t2-t1).TotalHours >24)){
//decide what to do.
return null;
}else{
var currentHour = t2.Hour;
var list = new List<String>();
for (int i=0;i<(t2-t1).TotalHours;i++){
if (currentHour<10){
list.Add("0"+currentHour+":00");
}else if (currentHour>=10){
list.Add(currentHour+":00");
}
currentHour= (currentHour+1)%24;
}
return list;
}
}
public IEnumerable<DateTime> GetHoursBetween(DateTime start, DateTime end)
{
DateTime first = start.Date.AddHours(start.Hour);
for (DateTime dateTime = first; dateTime <= end; dateTime = dateTime.AddHours(1))
{
yield return dateTime;
}
}
TimeSpan ts = DateTime1 - DateTime2;
double totalHours = ts.TotalHours;
From MSDN: "Gets the value of the current TimeSpan structure expressed in whole and fractional hours."
EDIT: ok, now I see what you're asking for. How about this:
var d1 = DateTime.Today.AddHours(9.5);
var d2 = DateTime.Today.AddHours(14);
var first = new DateTime(d1.Year, d1.Month, d1.Day, d1.Minute == 0 ? d1.Hour : d1.Hour + 1, 0, 0);
var second = new DateTime(d2.Year, d2.Month, d2.Day, d2.Minute == 0 ? d2.Hour : d2.Hour + 1, 0, 0);
TimeSpan ts = second - first;
//returns DateTimes affected. I.e., Today at, [10:00, 11:00, 12:00, 13:00, 14:00]
IEnumerable<DateTime> dates = Enumerable.Range(0, (int)ts.TotalHours + 1).Select(hour => first.AddHours(hour));
//Or, if you just want the HOURs
//returns just ints: i.e., DateTimes 10,11,12,13,14
IEnumerable<int> hours = Enumerable.Range(0, (int)ts.TotalHours + 1).Select(hour => first.AddHours(hour).Hour);
The first method is needed if you actually have dates that span days. If you DON'T, then the second method that just returns the hours would work fine.
This should do the trick. Tested in LinqPad.
var startDate = new DateTime(2013, 8, 7, 9, 30, 0);
var endDate = new DateTime(2013, 8, 7, 14, 0, 0);
List<string> times = new List<string>();
var currentTime = startDate;
if (currentTime.Minute != 0 || currentTime.Second != 0) {
// Get next hour
currentTime = currentTime.AddHours(1).AddMinutes(currentTime.Minute * -1);
}
while (currentTime <= endDate) {
times.Add(string.Format("{0:00}:00", currentTime.Hour));
currentTime = currentTime.AddHours(1);
}
(int)Math.Abs((date1 - date2).TotalHours)
Simply subtract them and get the total of hours from the result. Something like this:
var totalHours = (dateTime1 - dateTime2).TotalHours;
Maybe something like this would work?
public static List<DateTime> GetAffectedHours(DateTime start, DateTime end)
{
List<DateTime> result = new List<DateTime>();
// Strip start of its minutes/seconds/etc
DateTime initial = new DateTime(start.Year, start.Month, start.Day, start.Hour, 0, 0);
// Go ahead and get the next hour
DateTime iterator = initial.AddHours(1.0);
// if it is still before the end
while (iterator < end)
{
// add it to the results list
result.Add(iterator);
// and get the next hour
iterator = iterator.AddHours(1.0);
}
return result;
}
You can use a For loop
List<int> allHoursBetween = new List<int>();
for (DateTime d = myStartDate; d <= myEndDate; d = d.AddHours(1))
allHoursBetween.Add(d.Hour);
Related
How to subtract "year=117 month=1 day=28 hour=7 min=43 sec=10" from a DateTime in c#?
I have already tried like below
split the string using regex.
add each item with -ve sign to a current DateTime value.
But I think it's not an efficient way.
Can anyone help me?
You can use below Code as per you requirement to get desired Result. Replace your Date, Time, year values in "new System.DateTime(1996, 6, 3, 22, 15, 0);"
System.DateTime date1 = new System.DateTime(1996, 6, 3, 22, 15, 0);
System.DateTime date2 = new System.DateTime(1996, 12, 6, 13, 2, 0);
System.DateTime date3 = new System.DateTime(1996, 10, 12, 8, 42, 0);
// diff1 gets 185 days, 14 hours, and 47 minutes.
System.TimeSpan diff1 = date2.Subtract(date1);
// date4 gets 4/9/1996 5:55:00 PM.
System.DateTime date4 = date3.Subtract(diff1);
// diff2 gets 55 days 4 hours and 20 minutes.
System.TimeSpan diff2 = date2 - date3;
// date5 gets 4/9/1996 5:55:00 PM.
System.DateTime date5 = date1 - diff2;
you can try DateTime's subtraction.
for that first you have to make valid DateTime object from your information and then subtract that date from current date.
see below code,
int year = 117, month = 01, day = 28;
int hour = 07, minute = 43, second = 10;
DateTime timeToSubtract =
new DateTime(year > 0? year : 1, month > 0 ? month : 1, day > 0 ? day : 1, hour, minute, second);
DateTime subtractedDate =
new DateTime((DateTime.Now - timeToSubtract).Ticks);
as you can see, we are creating a date time object with information we have (date and time which should be subtracted form current date time) by, new DateTime(year, month, day, hour, minute, second) and then subtracting this from DateTime.Now, and then creating final date out of result of this subtraction.
here in last line we are creating a date (of past). this date is of specified time ago.
I'm trying to make a function in C# that returns the week difference between two dates. Its goal is to provide the same result of:
select datediff(ww,'2018-04-13','2018-04-16') as diff
In the example above there is only 3 days between these dates, but they are in different weeks, so the result should be 1.
I've tried to use .TotalDays but it's not working properly. I also tried .GetWeekOfYear but it won't return correctly when the year of the dates are different. I've seem many questions here on StackOverflow and on other forums and so far none of them match my case. This is the function I'm trying to far:
public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd) {
// Doesn't work
var val = ((dtEnd - dtStart).TotalDays / 7);
val = Math.Ceiling(val);
return Convert.ToInt32(val);
// Doesn't work well between years
DateTimeFormatInfo dinfo = DateTimeFormatInfo.CurrentInfo;
var x = dinfo.Calendar.GetWeekOfYear(dtStart, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
var y = dinfo.Calendar.GetWeekOfYear(dtEnd, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
return y - x;
}
In the first part of my function, I tried what is described in this post. It didn't work
Can you help me?
Thanks in advance.
First figure how many days there are between the two dates. Divide the number of days by 7 to get full weeks.
Now figure out if there's an extra week to be counted by finding taking the number of days modulus 7 to get any remaining days. If the first date plus remaining days falls in a different week, add an extra week on to the count.
void Main()
{
var first = new DateTime(2018, 04, 13);
var second = new DateTime(2018, 04, 16);
Console.WriteLine(weekDiff(first, second));
}
public int weekDiff(DateTime d1, DateTime d2, DayOfWeek startOfWeek = DayOfWeek.Monday)
{
var diff = d2.Subtract(d1);
var weeks = (int)diff.Days / 7;
// need to check if there's an extra week to count
var remainingDays = diff.Days % 7;
var cal = CultureInfo.InvariantCulture.Calendar;
var d1WeekNo = cal.GetWeekOfYear(d1, CalendarWeekRule.FirstFullWeek, startOfWeek);
var d1PlusRemainingWeekNo = cal.GetWeekOfYear(d1.AddDays(remainingDays), CalendarWeekRule.FirstFullWeek, startOfWeek);
if (d1WeekNo != d1PlusRemainingWeekNo)
weeks++;
return weeks;
}
static void Main(string[] args)
{
DateTime date1 = new DateTime(2018, 04, 18);
DateTime date2 = new DateTime(2018, 04, 19);
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 04, 18)))); // 0
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 22), new DateTime(2018, 04, 23)))); // 1
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 16), new DateTime(2018, 04, 22)))); // 0
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 05, 03)))); // 2
}
private static int GetDiff(DateTime date1, DateTime date2)
{
date1 = SetDayToMonday(date1);
date2 = SetDayToMonday(date2);
return (int)((date2 - date1).TotalDays / 7);
}
private static DateTime SetDayToMonday(DateTime date)
{
var weekDay = date.DayOfWeek;
if (weekDay == DayOfWeek.Sunday)
return date.AddDays(-6);
else
return date.AddDays(-((int)weekDay-1));
}
First, set the day to the monday of the current week. Then count all full weeks(= /7 days as int). Easy as it is, it works probably across weeks and years.
See if this works. There could be more use cases that this doesn't cover, and the solution depends on how you define a week boundary (this assumes Sunday-Monday based on a comment above).
// Output:
// Weeks between 12/28/2017 and 1/10/2018: 2
// Weeks between 4/13/2018 and 4/16/2018: 1
// Weeks between 4/21/2018 and 4/22/2018: 0
// Weeks between 4/22/2018 and 4/23/2018: 1
void Main()
{
var datePairs = new List<KeyValuePair<DateTime, DateTime>>();
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2017, 12, 28), new DateTime(2018, 1, 10)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 13), new DateTime(2018, 4, 16)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 21), new DateTime(2018, 4, 22)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 22), new DateTime(2018, 4, 23)));
foreach (var datePair in datePairs)
{
var string1 = datePair.Key.ToShortDateString();
var string2 = datePair.Value.ToShortDateString();
Console.WriteLine($"Weeks between {string1} and {string2}: {GetWeekDiff(datePair.Key, datePair.Value)}");
}
}
public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd)
{
var totalDays = (dtEnd - dtStart).TotalDays;
var weeks = (int)totalDays / 7;
var hasRemainder = totalDays % 7 > 0;
if (hasRemainder)
{
if (!(dtStart.DayOfWeek.Equals(DayOfWeek.Saturday) && dtEnd.DayOfWeek.Equals(DayOfWeek.Sunday)))
{
weeks++;
}
}
return weeks;
}
Maybe it can help
public static int GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
Get the correct week number of a given date
Can't comment yet and already used a flag on this post on something I believed to be similar. Here is another post I found that appears to align with the solution you are trying to create:
Get the number of calendar weeks between 2 dates in C#
This is my implementation to solve a similar problem, I haven't tested in thoroughly but it seems to work.
var dt1 = DateTime.Today.AddDays(-30);
var dt2 = DateTime.Today;
var noOfDays =(int) (dt2 - dt1).TotalDays;
int reminder;
var weeks = Math.DivRem(noOfDays, 7, out reminder);
weeks = reminder > 0 ? weeks + 1 : weeks;
It returns 1 week for 6 days or less gap, which is exactly what I needed.
Given this datetime of January 1 2015 at 23:00 hours:
var someDate = new DateTime(2015, 1, 1, 23, 0, 0);
And given the int 6, which is the desired hour, how do I return the first following datetime where the hour is 6? In this case, someDate and 6 would return a new DateTime of January 2 2015 at 06:00 hours.
I would simply add the hours to the original date and add another day if the result is before the original time:
var someDate = new DateTime(2015, 1, 1, 23, 0, 0);
var result = someDate.Date.AddHours(6); // note the "Date" part
if (result < someDate) result = result.AddDays(1);
You just have to add one day to the date and six hours to the result:
var someDate = new DateTime(2015, 1, 1, 23, 0, 0);
var result = someDate.Date.AddDays(1).AddHours(6);
Note the use of Date property - it will give you the start od the day and from there it's easy to navigate forward.
Try this:
while(someDate.Hour != 6){
someDate = someDate.AddHours(1);
}
Assuming you meant 24h clock, you can try this:
public DateTime GetDate(DateTime someDate,int hour)
{
return someDate.Hour>=hour? someDate.Date.AddDays(1).AddHours(6):someDate.Date.AddHours(6);
}
Something like this should do it:
public DateTime FollowingHour(DateTime start, int hour)
{
DateTime atHour = start.Date.AddHours(6);
if(atHour < start)
{
atHour += TimeSpan.FromDays(1);
}
return atHour;
}
I have run in a scenario where i need to find the total number of hours that falls on a current period. I Have a Time in and TimeOut datetime which i want to get the hours where the employee worked between 10pm-4am the following day. How would i get the output of hours worked.
I Created an Extension method like this:
public static decimal GetNightDifferentialValue(this DailyTime dtr, Employee201 employee, PayrollSettings settings, IEnumerable<Holidays> holidays)
{
//know if the time out is greater than 10pm of the dtr
//07-26-2016 14:00 - 07-27-2016 03:00
//if time out i
var days = Enumerable.Range(0, (int)(dtr.TimeOut - dtr.TimeIn).TotalHours + 1)
.Select(i => dtr.TimeIn.AddHours(i))
.Where(date => !(date.Hour >= 22)).Count();
return days* employee.Rate;
}
my problem is in the Where Method how can i Filter the hours that only fall on my category
public static decimal GetNightDifferentialValue(this DailyTime dtr, Employee201 employee, PayrollSettings settings, IEnumerable<Holidays> holidays)
{
//know if the time out is greater than 10pm of the dtr
//07-26-2016 14:00 - 07-27-2016 03:00
//if time out i
DateTime dayIn10pm = new DateTime(dtr.TimeIn.Year, dtr.TimeIn.Month, dtr.TimeIn.Day, 22, 0, 0);
DateTime dayAfter04am = dayIn10pm.Add(new TimeSpan(6,0,0));
var hours = Enumerable.Range(0, (int)(dtr.TimeOut - dtr.TimeIn).TotalHours + 1)
.Select(i => dtr.TimeIn.AddHours(i))
.Where(date => (date > dayIn10pm && date <= dayAfter04am)).Count();
return hours;
}
I see the problem is only with filtering, I would suggest compare Date part to determine is it next Date, if it is next date Look for TimeOfDay to compare Time
var t = TimeSpan.ParseExact("04:00:00", #"hh\:mm\:ss", CultureInfo.InvariantCulture);
var days = Enumerable.Range(0, (int)(dtr.TimeOut - dtr.TimeIn).TotalHours + 1)
.Select(i => dtr.TimeIn.AddHours(i))
.Where(date => (date.Date == TimeOut.Date && date.TimeOfDay <= t) || date.Hour >= 22)
.Count();
Check this Demo
I think this does what you want:
if (timeOut.Hour > 4)
{
timeOut = timeOut.Date.AddHours(4);
}
if (timeIn.Hour < 22)
{
timeIn = timeIn.Date.AddHours(22);
}
if (timeIn > timeOut)
{
// No overnight time
return 0;
}
var difference = timeOut - timeIn;
return difference.TotalHours;
Basically, we first normalize the dates:
If the employee got here before 10PM, consider he was there at 10PM
If the employee left after 4AM, consider he left at 4AM
From there, we just have to subtract the two dates, and handle the special case where the new timeIn is greater than the new timeOut (if, for instance, he worked from 2PM to 5PM). In which case it means there's no time between 10PM and 4AM, so we just return 0.
Note that this algorithm doesn't handle the case where the employee works more than 24 hours straight.
private void CalculateTotalHour(string dtstartTime, string dtendTime)
{
DateTime d1 = new DateTime();
d1 = Convert.ToDateTime(dtstartTime); DateTime d2 = new DateTime();
d2 = Convert.ToDateTime(dtendTime);
if (d1.Hour >= 12)
{
d1 = d1.AddDays(-1);
}
else if (d2.Hour >= 12)
{
d2 = d2.AddDays(1);
}
// if (d2 < d1)
// MessageBox.Show("shift end time is lesser than shift start time", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop);
TimeSpan ts = d2.Subtract(d1).Duration();
// ts.ToString(#"hh\:mm")//total dur
}
Get what I want but is not that good looking solution here is my solution:
var timeIn = new DateTime(2016, 7, 25, 14, 0, 0);
var timeOut = new DateTime(2016, 7, 26, 5, 0, 0);
if ((timeOut.Date - timeIn.Date).TotalDays >= 1)
{
var hrs12to4am = Enumerable.Range(0, (int)(timeOut - timeIn).TotalHours + 1)
.Select(i => timeIn.AddHours(i)).Where(a => a.Hour < 4 && a.Date > timeIn).ToList();
var hrsOverTen = Enumerable.Range(0, (int)(timeOut - timeIn).TotalHours + 1)
.Select(i => timeIn.AddHours(i)).Where(a => a.Hour > 22).ToList();
}
else
{
var hrsOverTen = Enumerable.Range(0, (int)(timeOut - timeIn).TotalHours + 1)
.Select(i => timeIn.AddHours(i)).Where(a => a.Hour > 22).ToList();
}
here is the demo Demo
i think this is your answer
int hours = (int)(dt2 - dt1).TotalHours;
My task is to find all Friday, 13 in a year that user inputs.
Can somebody explain how to do it? (I'm a beginner in c#)
int year = 2015;
for(int m=1; m<=12; m++)
{
var dt = new DateTime(year, m, 13);
if (dt.DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(dt.ToShortDateString());
}
To obtain the dates you may use Linq:
var dates = Enumerable
.Range(1, 12) // All months
.Select(month => new DateTime(2015, month, 13))
.Where(date => date.DayOfWeek == DayOfWeek.Friday);
To print out them
Console.WriteLine(String.Join(Environment.NewLine, dates));
If you want to get these dates in Gregorian Calender, you can use a combination of a loop, DateTime constructor and DayOfWeek enumeration like;
int year = 2015;
for (int i = 1; i < 13; i++)
{
if(new DateTime(year, i, 13).DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(new DateTime(year, i, 13));
}
For 2015, result will be;
13.02.2015 00:00:00
13.03.2015 00:00:00
13.11.2015 00:00:00
If you want to number of months, you can use .Month property of the result like;
Console.WriteLine((new DateTime(year, i, 13)).Month);
If you want to get your month names based on your CurrentCulture, you can use custom MMMM specifier like;
Console.WriteLine((new DateTime(year, i, 13)).ToString("MMMM"));
Also you can use Enumerable.Range like;
List<int> monthList = Enumerable.Range(1, 12).
Where(d => new DateTime(2015, d, 13).DayOfWeek == DayOfWeek.Friday).
ToList(); // {2, 3, 11}
or
List<string> monthList = Enumerable.Range(1, 12).
Where(d => new DateTime(2015, d, 13).DayOfWeek == DayOfWeek.Friday).
Select(m => new DateTime(2015, m, 13).ToString("MMMM", CultureInfo.InvariantCulture)).
ToList(); // {February, March, November}
Try to inspire by the code showed in that thread:
Finding every friday from start date till the end of the year
(of course you will have to check if selected Friday is 13th)
It can be done like this using linq.
var year = 2015;
var months = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var unluckyDays = months.Select(m => new DateTime(year, m, 13)).Where(dt => dt.DayOfWeek == DayOfWeek.Friday);
The first Select statement projects the list of integers into a list of datetimes representing the 13th of each month in the year specified.
Then simply filter this list to those where the day of the week is Friday.
DateTime objects have a property on them called DayOfWeek. You can utilize this to help you figure out if a date supplied returns a DayOfWeek Value of Friday: see below:
static void Main(string[] args)
{
for (var i = 1; i < 12; i++)
{
DateTime date = new DateTime(2015, i, 13);
if (date.DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(date.ToShortDateString());
}
Console.ReadLine();
}
Yes, it is quite simple
int year = 2014;
DateTime day = new DateTime(2014,1,1);
while (day.Year == year)
{
if (day.DayOfWeek == DayOfWeek.Friday && day.Day == 13)
{
Console.WriteLine(day);
}
day = day.AddDays(1);
}
You init a DateTime variable in the start of the year
Then you loop over each day of the year in this code I printed it
You can find more info of the DateTime class here
DateTime Day of the week
DateTime referenc in MSDN