Henry Olive 5 Posted June 23, 2023 (edited) Good Day, I need to find out if there is SUNDAY between 2 dates For example : StartDate = 06/23/2023 , EndDate = 06/26/2023 ( Result = 1 , Because 06/25/2023 = Sunday ) StartDate = 06/23/2023 , EndDate = 07/03/2023 ( Result = 2 , Because there are 2 Sundays ) StartDate = 06/23/2023 , EndDate = 06/24/2023 ( Result = 0 ) Thank You Edited June 23, 2023 by Henry Olive Share this post Link to post
Lajos Juhász 293 Posted June 23, 2023 you can ask AI to write this code. An anser from Bing function IsSundayBetween(StartDate, EndDate: TDateTime): Boolean; var Day: TDateTime; begin Result := False; // assume there is no Sunday between the dates Day := StartDate; // start from the start date while Day <= EndDate do // loop until the end date begin if DayOfWeek(Day) = 1 then // check if the day is Sunday begin Result := True; // set the result to true Break; // exit the loop end; Day := Day + 1; // increment the day by one end; end; Share this post Link to post
Sherlock 663 Posted June 23, 2023 Well SysUtils has a nifty function called DayOfWeek. It returns Integers between 1 and 7 where 1 is Sunday and Saturday is 7. The rest is simple. You might try @Lajos Juhász AI quote, or may get even shorter code by checking if 1 is in the range between StartDate and EndDate. Share this post Link to post
KodeZwerg 54 Posted June 23, 2023 How about: function CountSundays(const AStartDate, AEndDate: TDateTime): Integer; var LCurrentDate: TDateTime; LDirection: Integer; begin Result := 0; if AStartDate > AEndDate then LDirection := -1 // Search for Sundays in reverse order else LDirection := 1; // Search for Sundays in forward order LCurrentDate := AStartDate; while DayOfWeek(LCurrentDate) <> 1 do // Find the first Sunday LCurrentDate := LCurrentDate + LDirection; while (AStartDate < AEndDate) and (LCurrentDate <= AEndDate) or (AStartDate > AEndDate) and (LCurrentDate >= AEndDate) do begin Inc(Result); LCurrentDate := LCurrentDate + (7 * LDirection); // Jump to next/prior Sunday end; end; That approach works in both directions (ie: it does not matter what the start- and end- date is) Share this post Link to post
Uwe Raabe 2057 Posted June 23, 2023 (edited) How do you want to handle the case when both dates are equal as well as a Sunday? How, if they are not equal and both are a Sunday? Edited June 23, 2023 by Uwe Raabe Share this post Link to post
KodeZwerg 54 Posted June 23, 2023 10 minutes ago, Uwe Raabe said: How do you want to handle the case when both dates are equal as well as a Sunday? How, if they are not equal and both are a Sunday? I am sorry, here is a fixed version that also react for leap years... function CountSundays(const AStartDate, AEndDate: TDateTime): Integer; function MonthOf(const AValue: TDateTime): Word; var Year, Month, Day: Word; begin DecodeDate(AValue, Year, Month, Day); Result := Month; end; function YearOf(const AValue: TDateTime): Word; var Year, Month, Day: Word; begin DecodeDate(AValue, Year, Month, Day); Result := Year; end; function DayOf(const AValue: TDateTime): Word; var Year, Month, Day: Word; begin DecodeDate(AValue, Year, Month, Day); Result := Day; end; var LCurrentDate: TDateTime; LDirection: Integer; LDaysInMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); begin Result := 0; if AStartDate > AEndDate then LDirection := -1 // Search for Sundays in reverse order else LDirection := 1; // Search for Sundays in forward order LCurrentDate := AStartDate; while DayOfWeek(LCurrentDate) <> 1 do // Find the first Sunday LCurrentDate := LCurrentDate + LDirection; if (LDirection = 1) and (LCurrentDate = AEndDate) then Inc(Result) // Add 1 if the end date is a Sunday else if (LDirection = -1) and (LCurrentDate = AEndDate) and (DayOfWeek(AStartDate) = 1) then Inc(Result) // Add 1 if the start and end dates are the same and represent a Sunday else begin while (AStartDate < AEndDate) and (LCurrentDate <= AEndDate) or (AStartDate > AEndDate) and (LCurrentDate >= AEndDate) do begin Inc(Result); LCurrentDate := LCurrentDate + (7 * LDirection); // Increment to next Sunday if MonthOf(LCurrentDate) = 2 then // Adjust for leap year begin if IsLeapYear(YearOf(LCurrentDate)) then LDaysInMonth[2] := 29 else LDaysInMonth[2] := 28; end; if DayOf(LCurrentDate) > LDaysInMonth[MonthOf(LCurrentDate)] then // Adjust for end of month LCurrentDate := EncodeDate(YearOf(LCurrentDate), MonthOf(LCurrentDate) + 1, 1) - 1; end; end; end; Share this post Link to post
Sherlock 663 Posted June 23, 2023 uses System.DateUtils; function CheckForSunday(StartDate, EndDate: TDateTime): Boolean; var StartDay: Integer; EndDay: Integer; begin Result := Daysbetween(StartDate, EndDate) >= 7; if not Result then begin StartDay := DayofWeek(StartDate); EndDay := DayofWeek(EndDate); if (StartDay <= EndDay) then begin Result := (1 >= StartDay) and (1 <= EndDay) end else Result := True; end; end; OK, how does this look? I do have the assumption though, that StartDate lies before EndDate, saving one or two comparison steps. Share this post Link to post
Uwe Raabe 2057 Posted June 23, 2023 This is another approach without any loops: function CalcSundaysBetween(StartDate, EndDate: TDateTime): Integer; begin var D1 := Trunc(StartDate); var D2 := Trunc(EndDate); if D2 < D1 then begin var tmp := D1; D1 := D2; D2 := tmp; end; var offset := (D1 + 6) mod 7; Result := (D2 - D1 + offset) div 7; { check if lower date is a Sunday } if offset = 0 then Inc(Result); end; BTW, despite the title says, according to the examples in his post the OP seems to be more interested in the number of Sundays instead of just their existence. Share this post Link to post
Sherlock 663 Posted June 23, 2023 Just now, Uwe Raabe said: BTW, despite the title says, according to the examples in his post the OP seems to be more interested in the number of Sundays instead of just their existence. So I just noticed...well, then my code is a bit too simple. 😄 Share this post Link to post
mvanrijnen 123 Posted June 23, 2023 (edited) Yes, just experiented in Excel 🙂 pseudo: (DaysBetween(D2, D1) div 7) + ifthen(DayOfTheWeek(D1)=daySunday,1,0) ) + ifthen(DayOfTheWeek(D2)=daySunday,1,0) hmz, one off in some cases. pseudo (2): sundaycount := (DaysBetween(D2, D1) div 7); if (DayOfTheWeek(D1)=daySunday) or (DayOfTheWeek(D2)=daySunday) then sundaycount = sundaycount + 1; back to the drawing board 🙂 Edited June 23, 2023 by mvanrijnen 1 Share this post Link to post
Sherlock 663 Posted June 23, 2023 @mvanrijnen Ooh, that is cool. And easy enough to convert to Delphi: Quote function CheckForSundays(StartDate, EndDate: TDateTime): Integer; begin // (DaysBetween(D2, D1) div 7) + ifthen(DayOfTheWeek(D1)=daySunday,1,0) ) + ifthen(DayOfTheWeek(D2)=daySunday,1,0) Result := (DaysBetween(EndDate, StartDate) div 7) - IfThen(StartDay = EndDay, 1, 0); Result := Result + IfThen(DayOfWeek(StartDate) = 1, 1, 0); Result := Result + IfThen(DayOfWeek(EndDate) = 1, 1, 0); end; IfThen being in System.Math and DaysBetween in System.DateUtils. Edith has fixed extra sundays counted. Share this post Link to post
Sherlock 663 Posted June 23, 2023 9 minutes ago, mvanrijnen said: needs a check for friday-monday oh, darnit! Share this post Link to post
mvanrijnen 123 Posted June 23, 2023 (edited) working on it:) (wait for a batchjob to finish 🙂 so, can play around) UWE's method seems okay though Edited June 23, 2023 by mvanrijnen 1 Share this post Link to post
programmerdelphi2k 237 Posted June 27, 2023 (edited) On 6/23/2023 at 10:53 AM, Uwe Raabe said: This is another approach without any loops: @Henry Olive When evaluating how many "Sundays" between two dates, we must take into account the following: sundays between the two dates: 25, 26, 27, 28, 29, 30, 01, 02 = 0 sundays between 2 dates D1 = Jun/25 2023 = Sunday D2 = Jul/02 2023 = Sunday How many "Sundays" are there "BETWEEN" the two dates? A: 0 sundays Using AWE's answer, then, I think it needs revision, no? *answer = 2 sundays That is, as we want to know "how many Sundays exist between two dates, then, we could not take into account the initial and final date, even if they were Sundays, because we are looking for "Sundays between dates", not "Sundays in dates ". Edited June 27, 2023 by programmerdelphi2k Share this post Link to post
Uwe Raabe 2057 Posted June 27, 2023 56 minutes ago, programmerdelphi2k said: When evaluating how many "Sundays" between two dates, we must take into account the following: Yep, that was the background of these questions to the OP: On 6/23/2023 at 3:22 PM, Uwe Raabe said: How do you want to handle the case when both dates are equal as well as a Sunday? How, if they are not equal and both are a Sunday? The code I provided assumes that the start and end date are also counted when they fall on a Sunday. So unless the specification isn't refined any solution (start<=date<=end, start<date<=end, start<=date<end or start<date<end) is valid. Share this post Link to post
programmerdelphi2k 237 Posted June 27, 2023 (edited) 12 minutes ago, Uwe Raabe said: So unless the specification isn't refined any solution I think that is "well refined" not? any way... On 6/23/2023 at 9:40 AM, Henry Olive said: I need to find out if there is SUNDAY between 2 dates For example : StartDate = 06/23/2023 , EndDate = 06/26/2023 ( Result = 1 , Because 06/25/2023 = Sunday ) StartDate = 06/23/2023 , EndDate = 07/03/2023 ( Result = 2 , Because there are 2 Sundays ) StartDate = 06/23/2023 , EndDate = 06/24/2023 ( Result = 0 ) Edited June 27, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted June 27, 2023 46 minutes ago, Pat Foley said: No, Midnight starts new day! while YOU ARE in the "date", there is not any Mid-night... otherwise you would be in the next day! Share this post Link to post
Uwe Raabe 2057 Posted June 27, 2023 I am a bit baffled that the OP does not react at all. Share this post Link to post
Uwe Raabe 2057 Posted June 27, 2023 3 hours ago, programmerdelphi2k said: I think that is "well refined" not? It is not. The wording of the question leaves room for interpretation and the examples only cover the common case, but are leaving out the corner cases. If the specification were sufficient, I wouldn't have asked my questions. Share this post Link to post
programmerdelphi2k 237 Posted June 27, 2023 1 hour ago, Uwe Raabe said: If the specification were sufficient, I wouldn't have asked my questions. I can also interpret that, with advancing age, many things become difficult to interpret or "accept", so, to finish the succinct question and disagreements: YOU WON and I lost! Period! the said for the unspoken, and, we're all going to have a smooth and cold beer to cool the neurons! Share this post Link to post
Dave Nottage 557 Posted June 27, 2023 (edited) I figured it had to be fairly simple. Can someone poke holes in this? It assumes you're passing a valid value for ADayOfWeek. Also assumes the start/end dates should count uses System.DateUtils; function DayOfWeekCountBetween(const ADayOfWeek: Word; const ANow, AThen: TDateTime): Word; var LDate: TDateTime; begin Result := 0; if AThen >= ANow then begin LDate := ANow; repeat if DayOfWeek(LDate) = ADayOfWeek then Inc(Result); LDate := LDate + 1; until LDate > AThen; end else Result := DayOfWeekCountBetween(ADayOfWeek, AThen, ANow); end; Edited June 27, 2023 by Dave Nottage Share this post Link to post