נבוך באלגוריתם - חיפוש ימים בשבוע בתוך טווח תאריכים
-
שלום לכולם.
מדובר במורה מקצועי שעובד על בסיס שבועי ולא כל השבוע (נניח משני עד רביעי ס"ה 3 ימים בשבוע), כאשר רצונינו לראות כמה ימים עבד המורה בתוך טווח תאריכים נתון, שהתאריך יכול להתחיל ולהסתיים באמצע השבוע, זהו אלגוריתמינו.
פונקציה שמקבלת טווח תאריכים, וטווח ימים רצופים בשבוע, ומחזירה את סך הימים שבהם המורה עבד בטווח הנתון.
Function GetWeekDaysCountBetweenDates(FromDate As Date, ToDate As Date, FromDay As Integer, ToDay As Integer) As Integer Dim FullWeeks As Integer, Total As Long If DatePart("w", FromDate) = 1 And DatePart("w", ToDate) = 7 Then GetWeekDaysCountBetweenDates = (CLng(ToDate - FromDate) / 7) * ((ToDay - FromDay) + 1) Else FullWeeks = Max(CLng((ToDate - DatePart("w", ToDate)) - (FromDate - (7 - DatePart("w", ToDate)))), 0) 'חישוב השבועות השלמים Total = Total + FullWeeks * ((ToDay - FromDay) + 1) 'מוסיף לסכום את הימים של השבוע הראשון וזה מכסה גם מצב שבו אין שבועות שלמים כלל If DatePart("w", FromDate) <= ToDay Then Total = Total + ((ToDay - Max(FromDay, DatePart("w", FromDate))) + 1) End If 'מוסיף לסכום את הימים של השבוע האחרון If DatePart("w", ToDate) >= FromDay And FullWeeks > 0 Then 'מוכרח שיש שבוע שלם אחד לפחות דאם לא כן הרי השבוע מטופל בתור שבוע ראשון ואין לטפל בו גם כשבוע אחרון Total = Total + ((Min(ToDay, DatePart("w", ToDate)) - FromDay) + 1) End If GetWeekDaysCountBetweenDates = Total End If End Function
לא מצליח להגיע לקוד נקי ומצוחצח ולא רוצה לעשות עבודה ערבית עמוסת if או cases.
תשאלו מה רע במה שעשיתי?? הנה תכניסו את הפונקציה כך:
GetWeekDaysCountBetweenDates(#24/01/2015# ,#28/01/2015#,2,2)נ.ב. זה קוד VBA יש פונקציות משנה נדרשות כדלהלן:
Function Min(var1, var2) If IsNull(var1) And IsNull(var2) Then Exit Function If IsNull(var1) Then Min = var2: Exit Function If IsNull(var2) Then Min = var1: Exit Function If var1 < var2 Then Min = var1 Else Min = var2 End If End Function Function Max(var1, var2) If IsNull(var1) And IsNull(var2) Then Exit Function If IsNull(var1) Then Max = var2: Exit Function If IsNull(var2) Then Max = var1: Exit Function If var1 > var2 Then Max = var1 Else Max = var2 End If End Function
פורסם במקור בפורום CODE613 ב28/01/2015 13:28 (+02:00)
-
ממש בשליפה, הייתי כותב את הפונקצייה ככה:
Function GetWeekDaysCountBetweenDates(FromDate As Date, ToDate As Date, FromDay As Integer, ToDay As Integer) As Integer ' משתנה טוטאל Dim Total As Integer ' משתנה מערך עבור הימים Dim arr(7) As Variant 'הכנסת הימים שנבחרו למערך, באותה דרך אפשר להעביר לפונקצייה ימים לא רציפים כמערך, או מופרד בפסיקים ואחר כך SPLIT For i = FromDay To ToDay arr(i) = i Next i Dim fdate As Date ' מעבר על כל התאריכים ובדיקה אם היום בשבוע של התאריך נמצא במערך For fdate = FromDate To ToDate If (UBound(Filter(arr, DatePart("w", fdate))) > -1) Then 'אםהיום נמצא במערך, מוסיפים 1 לטוטאל Total = Total + 1 End If Next ' החזרת התוצאה GetWeekDaysCountBetweenDates = Total End Function
מה אתה אומר?
פורסם במקור בפורום CODE613 ב28/01/2015 23:14 (+02:00)
-
מה אתה אומר?
הוא יאמר שזה עובד אבל אלגוריתם לא יעיל.
תראה יש לנו מס' ימים, ויש לנו יום בשבוע שחל היום הראשון.
אז החשבון פשוט: (מס' הימים - היום בשבוע) / 7. זה נותן שבועות שלמים, עם שארית.
כל מה שנשאר לנתח את השבוע הראשון ואת השארית של החלוקה הנ"ל.פורסם במקור בפורום CODE613 ב29/01/2015 00:08 (+02:00)
-
@דוד ל.ט.
מה אתה אומר?
הוא יאמר שזה עובד אבל אלגוריתם לא יעיל.
תראה יש לנו מס' ימים, ויש לנו יום בשבוע שחל היום הראשון.
אז החשבון פשוט: (מס' הימים - היום בשבוע) / 7. זה נותן שבועות שלמים, עם שארית.
כל מה שנשאר לנתח את השבוע הראשון ואת השארית של החלוקה הנ"ל.ככה זה כשאתה נמצא בבית חולים, הראש מפסיק לעבוד
פורסם במקור בפורום CODE613 ב29/01/2015 01:07 (+02:00)
-
לא יודע VB אבל למה לא משהו כזה?
boolean Day[7] int Days Day[0]:=0, Day[1]:=0, Day[2]:=1, Day[3]:=1, Day[4]:=1, Day[5]:=0, Day[6]:=0 Days:=GetSumDays(FromDay, ToDay) FirstDay:=DayOfWeek(00/00/0000) for i:=1 to Days do JobDay+=Day[(FirstDay mod 7)] FirstDay += 1 End For return JobDay
פורסם במקור בפורום CODE613 ב29/01/2015 08:22 (+02:00)
-
לא יודע VB אבל למה לא משהו כזה?
boolean Day[7] int Days Day[0]:=0, Day[1]:=0, Day[2]:=1, Day[3]:=1, Day[4]:=1, Day[5]:=0, Day[6]:=0 Days:=GetSumDays(FromDay, ToDay) FirstDay:=DayOfWeek(00/00/0000) for i:=1 to Days do JobDay+=Day[(FirstDay mod 7)] FirstDay += 1 End For return JobDay
יפה מאוד! קוד מובן ומעניין.
אבל שוב לא יעיל, באמת חייבים לעבור בלולאה על 10000 יום?
הרי ידוע בדיוק כמה שבועות שלמים, ואת המודולו צריך לעשות רק על השבר הראשון והאחרון.פורסם במקור בפורום CODE613 ב29/01/2015 13:32 (+02:00)
-
נראה לי שתיקנתי עד שהלקוח יתקשר יום אחד שגנבתי לו מאות אלפי שקלים של משכורות :lol: :lol: :lol: סתם יש כאן שמורות מתמטיות וזה באמת עובד טוב...
Function GetWeekDaysCountBetweenDates(FromDate As Date, ToDate As Date, FromDay As Integer, ToDay As Integer) As Integer Dim FullWeeks As Integer, Total As Long If DatePart("w", FromDate) = 1 And DatePart("w", ToDate) = 7 Then GetWeekDaysCountBetweenDates = (CLng(ToDate - FromDate) / 7) * ((ToDay - FromDay) + 1) Else FullWeeks = Max(Fix(CLng((ToDate - DatePart("w", ToDate)) - (FromDate - (7 - DatePart("w", FromDate)))) / 7), 0) 'חישוב השבועות השלמים Total = Total + FullWeeks * ((ToDay - FromDay) + 1) 'מוסיף לסכום את הימים של השבוע הראשון וזה מכסה גם מצב שבו אין שבועות שלמים כלל If DatePart("w", FromDate) <= ToDay Then Total = Total + ((ToDay - Max(FromDay, DatePart("w", FromDate))) + 1) End If 'מוסיף לסכום את הימים של השבוע האחרון If DatePart("w", ToDate) >= FromDay And FullWeeks > 0 Then 'מוכרח שיש שבוע שלם אחד לפחות דאם לא כן הרי השבוע מטופל בתור שבוע ראשון ואין לטפל בו גם כשבוע אחרון Total = Total + ((Min(ToDay, DatePart("w", ToDate)) - FromDay) + 1) End If GetWeekDaysCountBetweenDates = Total End If End Function
פורסם במקור בפורום CODE613 ב29/01/2015 16:00 (+02:00)
-
@דוד ל.ט.
@אהרן
לא יודע VB אבל למה לא משהו כזה?boolean Day[7] int Days Day[0]:=0, Day[1]:=0, Day[2]:=1, Day[3]:=1, Day[4]:=1, Day[5]:=0, Day[6]:=0 Days:=GetSumDays(FromDay, ToDay) FirstDay:=DayOfWeek(00/00/0000) for i:=1 to Days do JobDay+=Day[(FirstDay mod 7)] FirstDay += 1 End For return JobDay
יפה מאוד! קוד מובן ומעניין.
אבל שוב לא יעיל, באמת חייבים לעבור בלולאה על 10000 יום?
הרי ידוע בדיוק כמה שבועות שלמים, ואת המודולו צריך לעשות רק על השבר הראשון והאחרון.מה הבעיה, איטיות?
פורסם במקור בפורום CODE613 ב29/01/2015 20:56 (+02:00)
-
איזה ציון מגיע לי?
boolean Day[7] int Days Day[0]:=0, Day[1]:=0, Day[2]:=1, Day[3]:=1, Day[4]:=1, Day[5]:=0, Day[6]:=0 Days:=GetSumDays(FromDay, ToDay) FirstDay:=DayOfWeek(00/00/0000) Days -: ( 7 - FirstDay ) LastDay := Days mod 7 SunWeeks := Days div 7 for i:=1 to 7 do \\ FirstWeek JobDay += ( Day[i-1] * ( i= > FirstDay )) \\ LastWeek JobDay += ( Day[i-1] * (i =< LastDay )) \\ NormalWeek JobDay += Day[i-1] * SunWeeks End For return JobDay
פורסם במקור בפורום CODE613 ב01/02/2015 20:20 (+02:00)