Jump to content
Henry Olive

Is there a Sunday between 2 dates ?

Recommended Posts

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 by Henry Olive

Share this post


Link to post

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

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

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

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 by Uwe Raabe

Share this post


Link to post
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
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

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
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

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 by mvanrijnen
  • Thanks 1

Share this post


Link to post

@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
9 minutes ago, mvanrijnen said:

needs a check for friday-monday  

oh, darnit!

Share this post


Link to post

working on it:)

(wait for a batchjob to finish 🙂 so, can play around)

 

UWE's method seems okay though

Edited by mvanrijnen
  • Like 1

Share this post


Link to post
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 ".

 

image.png.5d404c7d5b5b95e95cbe6a075a232f8b.png

Edited by programmerdelphi2k

Share this post


Link to post
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
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 by programmerdelphi2k

Share this post


Link to post
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
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
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

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 by Dave Nottage

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×