දින පරාස දෙකක් ලබා දී ඇති විට, දින පරාස දෙක අතිච්ඡාදනය වේද යන්න තීරණය කිරීමට සරලම හෝ වඩාත්ම කාර්යක්ෂම ක්රමය කුමක්ද?
උදාහරණයක් ලෙස, අපි දිනයවේලාව විචල්ය මගින් වන වැටි හිතන්න StartDate1
කිරීමට EndDate1
හා StartDate2
කිරීමට EndDate2
.
දින පරාස දෙකක් ලබා දී ඇති විට, දින පරාස දෙක අතිච්ඡාදනය වේද යන්න තීරණය කිරීමට සරලම හෝ වඩාත්ම කාර්යක්ෂම ක්රමය කුමක්ද?
උදාහරණයක් ලෙස, අපි දිනයවේලාව විචල්ය මගින් වන වැටි හිතන්න StartDate1
කිරීමට EndDate1
හා StartDate2
කිරීමට EndDate2
.
Answers:
(StartA <= EndB) සහ (EndA> = StartB)
සාධනය:
ConditionA යන්නෙන් අදහස් වන්නේ DateRange B දිනයෙන් පසුව සම්පූර්ණයෙන්ම වෙනස් වන බවයි
_ |---- DateRange A ------|
|---Date Range B -----| _
(සත්ය නම් StartA > EndB
)
ConditionB යන්නෙන් අදහස් කරන්නේ DateRange A සම්පූර්ණයෙන්ම DateRange B ට පෙර බවයි
|---- DateRange A -----| _
_ |---Date Range B ----|
(සත්ය නම් EndA < StartB
)
A හෝ B සත්ය නොවේ නම් අතිච්ඡාදනය පවතී -
(එක් පරාසයක් සම්පූර්ණයෙන්ම අනෙකට පසුව
හෝ සම්පූර්ණයෙන්ම අනෙකට පෙර නොවේ නම් ඒවා අතිච්ඡාදනය විය යුතුය.)
දැන් ඩි මෝගන්ගේ එක් නීතියක් මෙසේ පවසයි:
Not (A Or B)
<=> Not A And Not B
පරිවර්තනය කරන්නේ: (StartA <= EndB) and (EndA >= StartB)
සටහන: දාර හරියටම අතිච්ඡාදනය වන කොන්දේසි මෙයට ඇතුළත් වේ. ඔබ ඉවත් කිරීමට කැමති නම්,
මේ වෙනස් >=
ක්රියාකරුවන් >
, සහ <=
කිරීමට<
සටහන 2. @Baodad ස්තුති, බලන්න මේ බ්ලොග් , සැබෑ එකක් උඩ එකක් අවම වශයෙන් වේ:
{ endA-startA
, endA - startB
, endB-startA
, endB - startB
}
(StartA <= EndB) and (EndA >= StartB)
(StartA <= EndB) and (StartB <= EndA)
සටහන 3. @ ටොමොසියස්ට ස්තූතියි, කෙටි අනුවාදයක් මෙසේ කියැවේ:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
මෙය සැබවින්ම දිගු ක්රියාත්මක කිරීමක් සඳහා වූ සින්ටැක්ටිකල් කෙටිමඟකි, ආරම්භක දිනයන් අවසන් දිනට පෙර හෝ ඊට පෙර බව තහවුරු කර ගැනීම සඳහා අමතර චෙක්පත් ඇතුළත් වේ. මෙය ඉහළින් උපුටා ගැනීම:
ආරම්භක හා අවසන් දිනයන් පිළිවෙලට තිබිය හැකි නම්, එනම්, හැකි නම් startA > endA
හෝ startB > endB
, ඒවා පිළිවෙලට තිබේදැයි පරීක්ෂා කර බැලිය යුතුය, එවිට එයින් අදහස් වන්නේ ඔබට අතිරේක වලංගු නීති දෙකක් එකතු කළ යුතු බවයි:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)
හෝ:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)
හෝ,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))
හෝ:
(Max(StartA, StartB) <= Min(EndA, EndB)
නමුත් ක්රියාත්මක කිරීම සඳහා Min()
සහ Max()
ඔබ කේත කළ යුතුය, (ආතතිය සඳහා සී ටර්නරි භාවිතා කිරීම) ,:
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)
Start
සහ End
අර්ථය හරියටම එයයි . ඔබට ඉහළ සහ පහළ, හෝ නැගෙනහිර සහ බටහිර, හෝ හයිවේලූ සහ ලෝවාලූ යන විචල්යයන් දෙකක් තිබේ නම්, යම් දෙයක් හෝ යමෙකු, කොතැනක හෝ සාරධර්ම යුගලයක් ප්රතිවිරුද්ධ විචල්යයන්හි ගබඩා නොවන බවට සහතික විය යුතු යැයි උපකල්පනය කළ හැකිය. යුගල දෙකෙන් එකක් පමණක් නිසා, අගයන් යුගල දෙකම මාරු කළ හොත් එය ද ක්රියා කරයි.
start
අතර end
("ශුන්ය ආරම්භය" = "කාලය ආරම්භයේ සිට" සහ "ශුන්ය අවසානය" = "කාලය අවසානය" යන අර්ථකථනය සමඟ):(startA === null || endB === null || startA <= endB) && (endA === null || startB === null || endA >= startB)
DateRangesOverlap = max(start1, start2) < min(end1, end2)
පරාසය දෙක අතිච්ඡාදනය වුවහොත් එය ප්රමාණවත් යැයි මම විශ්වාස කරමි:
(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
(StartDate1 <= EndDate2) and (EndDate1 >= StartDate2)
අංකනය තේරුම් ගැනීමට පහසු බව මට පෙනේ , Range1 සෑම විටම පරීක්ෂණ වල වම්පස ඇත.
<=
කිරීමට <
ආරම්භ ඇතුළත් වන අතර, අවසන් සුවිශේෂී වන්නේ නම්.
මෙම ලිපිය .NET සඳහා ගතවන කාලය ඒ කාලය පුස්තකාලය ගණන් ගන්නා විසින් කාල දෙකක් ඇති සම්බන්ධය විස්තර PeriodRelation :
// ------------------------------------------------------------------------
public enum PeriodRelation
{
After,
StartTouching,
StartInside,
InsideStartTouching,
EnclosingStartTouching,
Enclosing,
EnclosingEndTouching,
ExactMatch,
Inside,
InsideEndTouching,
EndInside,
EndTouching,
Before,
} // enum PeriodRelation
තාවකාලික සම්බන්ධතා පිළිබඳ තර්ක කිරීම සඳහා (හෝ වෙනත් ඕනෑම අන්තර් සම්බන්ධතා, ඒ වෙත පැමිණෙන්න), ඇලන්ගේ අන්තර්වාර වීජ ගණිතය සලකා බලන්න . එකිනෙකට සාපේක්ෂව කාල පරතරයන් දෙකක් තිබිය හැකි සම්බන්ධතා 13 ක් එය විස්තර කරයි. ඔබට වෙනත් යොමු කිරීම් සොයාගත හැකිය - "ඇලන් ඉන්ටර්වෙල්" යනු ක්රියාකාරී සෙවුම් පදයකි. ස්නොඩ්ග්රෑස් හි කාලානුරූපී යෙදුම් සංවර්ධනය කිරීමේ SQL (පී.ඩී.එෆ්. යූආර්එල් වෙතින් ලබා ගත හැකිය), සහ දිනය, ඩාර්වන් සහ ලොරෙන්ට්සෝස් තාවකාලික දත්ත සහ සම්බන්ධතා ආකෘතිය (2002) හෝ වේලාව සහ සම්බන්ධතා න්යාය: තාවකාලික දත්ත සමුදායන් තුළ ඔබට මෙම මෙහෙයුම් පිළිබඳ තොරතුරු සොයාගත හැකිය . සම්බන්ධතා ආකෘතිය සහ SQL (2014; T ලදායී ලෙස TD&RM හි දෙවන සංස්කරණය).
කෙටි (ඊෂ්) පිළිතුර නම්: දින දෙකක කාල පරතරයන් A
සහ B
සංරචක .start
සහ .end
අවහිරතා සහිතව .start <= .end
, පසුව අන්තරයන් දෙකක් අතිච්ඡාදනය වන්නේ නම්:
A.end >= B.start AND A.start <= B.end
ඔබ පදයට භාවිතය හැකි >=
එදිරිව >
හා <=
එදිරිව <
එකක් උඩ එකක් උපාධිය සඳහා ඔබගේ අවශ්යතා සපුරාලීම සඳහා.
එරික් අදහස්:
ඔබට ලැබිය හැක්කේ ඔබ විහිලු දේවල් ලෙස ගණන් ගන්නේ නම් පමණි ... මට පිස්සු වැටෙන විට "අන්තරයන් දෙකකට තිබිය හැකි සම්බන්ධතා 15 ක්" ලබා ගත හැකිය. සංවේදී ගණනය කිරීම් වලින්, මට ලැබෙන්නේ හයක් පමණි, ඔබ මුලින්ම ඒ හෝ බී එන්නේ දැයි සැලකිලිමත් වුවහොත්, මට ලැබෙන්නේ තුනක් පමණි (කිසිදු මංසන්ධියක්, අර්ධ වශයෙන් ඡේදනය නොවේ, එකක් මුළුමනින්ම අනෙකක් තුළ). 15 මේ ආකාරයට යයි: [පෙර: පෙර, ආරම්භ, ඇතුළත, අවසානය, පසු], [ආරම්භය: ආරම්භ කරන්න, ඇතුළත, අවසානය, පසු], [ඇතුළත: ඇතුළත, අවසානය, පසු], [අවසානය: අවසානය, පසු], [අවසානය: අවසානය, පසු], [ පසු: පසු].
'පෙර: පෙර' සහ 'පසු: පසු' යන සටහන් දෙක ඔබට ගණන් කළ නොහැකි යැයි මම සිතමි. ඔබ යම් සම්බන්ධතා ඒවායේ ප්රතිලෝම සමඟ සමාන කළහොත් මට සටහන් 7 ක් දැකිය හැකිය (යොමු කරන ලද විකිපීඩියා URL හි රූප සටහන බලන්න; එයට ඇතුළත් කිරීම් 7 ක් ඇත, ඒවායින් 6 ක් වෙනස් ප්රතිලෝමයක් ඇති අතර සමාන ප්රතිලෝමයක් නොමැත). තුනක් සංවේදීද යන්න ඔබගේ අවශ්යතා මත රඳා පවතී.
----------------------|-------A-------|----------------------
|----B1----|
|----B2----|
|----B3----|
|----------B4----------|
|----------------B5----------------|
|----B6----|
----------------------|-------A-------|----------------------
|------B7-------|
|----------B8-----------|
|----B9----|
|----B10-----|
|--------B11--------|
|----B12----|
|----B13----|
----------------------|-------A-------|----------------------
අතිච්ඡාදනය ගණනය කළ යුතු නම්, ඔබට පහත සූත්රය භාවිතා කළ හැකිය:
overlap = max(0, min(EndDate1, EndDate2) - max(StartDate1, StartDate2))
if (overlap > 0) {
...
}
එකිනෙකට සාපේක්ෂව පරාසයන් පවතින්නේ කොතැනද යන්න මත පදනම්ව කොන්දේසි රාශියක් පරීක්ෂා කරන සියලු විසඳුම් නිශ්චිත පරාසයක් කලින් ආරම්භ වන බව සහතික කිරීමෙන් බොහෝ සෙයින් සරල කළ හැකිය ! අවශ්ය නම් පරාසය පෙරට මාරු කිරීමෙන් පළමු පරාසය කලින් (හෝ ඒ සමඟම) ආරම්භ වන බව ඔබ සහතික කරයි.
එවිට, අනෙක් පරාසයේ ආරම්භය පළමු පරාසයේ අවසානයට වඩා අඩු හෝ සමාන නම් (පරාසයන් ඇතුළත් නම්, ආරම්භක හා අවසාන වේලාවන් දෙකම අඩංගු වේ නම්) හෝ ඊට වඩා අඩු නම් (පරාසයන් ආරම්භක සහ අවසානයෙන් බැහැර නම්) .
දෙපසම ඇතුළත් යැයි උපකල්පනය කළහොත්, අතිච්ඡාදනය නොවන අවස්ථා හතරක් ඇත:
|----------------------| range 1
|---> range 2 overlap
|---> range 2 overlap
|---> range 2 overlap
|---> range 2 no overlap
2 පරාසයේ අවසාන ලක්ෂ්යය එයට ඇතුල් නොවේ. එබැවින්, ව්යාජ කේතයකින්:
def doesOverlap (r1, r2):
if r1.s > r2.s:
swap r1, r2
if r2.s > r1.e:
return false
return true
මෙය ඊටත් වඩා සරල කළ හැකිය:
def doesOverlap (r1, r2):
if r1.s > r2.s:
swap r1, r2
return r2.s <= r1.e
පරාසය ආරම්භයේ දී ඇතුළත් වී අවසානයේ දී පමණක් නම්, ඔබට දෙවන ප්රකාශය >
සමඟ ප්රතිස්ථාපනය කළ >=
යුතුය if
(පළමු කේත කොටස සඳහා: දෙවන කේත කොටසෙහි, ඔබ භාවිතා කරන්නේ ඒ <
වෙනුවට <=
):
|----------------------| range 1
|---> range 2 overlap
|---> range 2 overlap
|---> range 2 no overlap
|---> range 2 no overlap
පරාසය 1 කිසි විටෙකත් 2 වන පරාසයෙන් පසුව ආරම්භ නොවන බව සහතික කිරීමෙන් ඔබ විසින් කළ යුතු චෙක්පත් ගණන බොහෝ සෙයින් සීමා කරයි.
ජාවාස්ක්රිප්ට් භාවිතා කරන තවත් විසඳුමක් මෙන්න. මගේ විසඳුමේ විශේෂතා:
පරීක්ෂණ පදනම් වී ඇත්තේ පූර්ණ සංඛ්යා මත වන නමුත් ජාවාස්ක්රිප්ට් හි දින වස්තු සැසඳිය හැකි බැවින් ඔබට දින වස්තු දෙකකට ද විසි කළ හැකිය. නැතහොත් ඔබට මිලි තත්පර කාලරාමුව තුළට විසි කළ හැකිය.
/**
* Compares to comparable objects to find out whether they overlap.
* It is assumed that the interval is in the format [from,to) (read: from is inclusive, to is exclusive).
* A null value is interpreted as infinity
*/
function intervalsOverlap(from1, to1, from2, to2) {
return (to2 === null || from1 < to2) && (to1 === null || to1 > from2);
}
describe('', function() {
function generateTest(firstRange, secondRange, expected) {
it(JSON.stringify(firstRange) + ' and ' + JSON.stringify(secondRange), function() {
expect(intervalsOverlap(firstRange[0], firstRange[1], secondRange[0], secondRange[1])).toBe(expected);
});
}
describe('no overlap (touching ends)', function() {
generateTest([10,20], [20,30], false);
generateTest([20,30], [10,20], false);
generateTest([10,20], [20,null], false);
generateTest([20,null], [10,20], false);
generateTest([null,20], [20,30], false);
generateTest([20,30], [null,20], false);
});
describe('do overlap (one end overlaps)', function() {
generateTest([10,20], [19,30], true);
generateTest([19,30], [10,20], true);
generateTest([10,20], [null,30], true);
generateTest([10,20], [19,null], true);
generateTest([null,30], [10,20], true);
generateTest([19,null], [10,20], true);
});
describe('do overlap (one range included in other range)', function() {
generateTest([10,40], [20,30], true);
generateTest([20,30], [10,40], true);
generateTest([10,40], [null,null], true);
generateTest([null,null], [10,40], true);
});
describe('do overlap (both ranges equal)', function() {
generateTest([10,20], [10,20], true);
generateTest([null,20], [null,20], true);
generateTest([10,null], [10,null], true);
generateTest([null,null], [null,null], true);
});
});
කර්මය සහ ජැස්මින් සහ ෆැන්ටම් ජේඑස් සමඟ ධාවනය වන විට ප්රති ult ලය:
PhantomJS 1.9.8 (ලිනක්ස්): 20 න් 20 ක් ක්රියාත්මක කරන ලදි (තත්පර 0.003 / තත්පර 0.004)
මැජික් කරන කේතය මෙන්න:
var isOverlapping = ((A == null || D == null || A <= D)
&& (C == null || B == null || C <= B)
&& (A == null || B == null || A <= B)
&& (C == null || D == null || C <= D));
කොහෙද ..
සාක්ෂි? මෙම පරීක්ෂණ කොන්සෝල කේත සාරාංශය බලන්න .
මම කරන්නම්
StartDate1.IsBetween(StartDate2, EndDate2) || EndDate1.IsBetween(StartDate2, EndDate2)
කොහෙද IsBetween
වගේ දෙයක්
public static bool IsBetween(this DateTime value, DateTime left, DateTime right) {
return (value > left && value < right) || (value < left && value > right);
}
ජාවා හි මගේ විසඳුම මෙන්න , එය අසීමිත කාල පරාසයන් තුළ ද ක්රියා කරයි
private Boolean overlap (Timestamp startA, Timestamp endA,
Timestamp startB, Timestamp endB)
{
return (endB == null || startA == null || !startA.after(endB))
&& (endA == null || startB == null || !endA.before(startB));
}
!startA.after(endB)
startA <= endB !endA.before(startB)
යන්නෙන් අදහස් වන්නේ startB <= endA යන්නයි. මේවා සංවෘත කාල පරතරයක් සඳහා වන නිර්ණායක මිස විවෘත කාල පරතරයක් නොවේ.
endB == null
හා startA == null
විවෘත පරතරය සඳහා පරික්ෂා කරන්න.
endB == null
, startA == null
, endA == null
සහ startB == null
ක ගොඩගසමින් පරතරය නොව විවෘත පරතරය සඳහා පරීක්ෂා කිරීමට සියලු නිර්ණායක වේ. අසීමිත හා විවෘත කාල පරතරයන් අතර වෙනස සඳහා උදාහරණය: (10, 20) සහ (20, ශුන්ය) අතිච්ඡාදනය නොවන විවෘත කාල පරතරයන් දෙකකි. අන්තිමයාට අසීමිත අවසානයක් ඇත. ඔබේ ක්රියාකාරිත්වය සත්ය වනු ඇත, නමුත් අන්තරයන් අතිච්ඡාදනය නොවේ, මන්ද එම කාල පරතරයන් 20 ක් ඇතුළත් නොවන බැවිනි. (සරල බව සඳහා කාලරාමු වෙනුවට භාවිතා කළ සංඛ්යා)
මෙහි පළ කර ඇති විසඳුම අතිච්ඡාදනය වන සියලු පරාසයන් සඳහා ක්රියා කළේ නැත ...
---------------------- | ------- ඒ ------- | ----------- ----------- | ---- බී 1 ---- | | ---- බී 2 ---- | | ---- බී 3 ---- | | ---------- බී 4 ---------- | | ---------------- බී 5 ---------------- | | ---- බී 6 ---- | ---------------------- | ------- ඒ ------- | ----------- ----------- | ------ B7 ------- | | ---------- බී 8 ----------- | | ---- බී 9 ---- | | ---- බී 10 ----- | | -------- බී 11 -------- | | ---- බී 12 ---- | | ---- බී 13 ---- | ---------------------- | ------- ඒ ------- | ----------- -----------
මගේ වැඩ කරන විසඳුම වූයේ:
සහ ( ('start_date' BARTWEEN STARTDATE AND ENDDATE) - අභ්යන්තර හා අවසාන දිනය පිටත සපයයි හෝ ('end_date' BARTWEEN STARTDATE AND ENDDATE) - අභ්යන්තර සහ ආරම්භක දිනය පිටත සපයයි හෝ (STARTDATE 'start_date' සහ 'end_date') - පිටත පරාසයන් සඳහා දිනයන් ඇතුළත අවශ්ය වන්නේ එකක් පමණි. )
Moment.js සමඟ මෙය මගේ ජාවාස්ක්රිප්ට් විසඳුම විය:
// Current row dates
var dateStart = moment("2014-08-01", "YYYY-MM-DD");
var dateEnd = moment("2014-08-30", "YYYY-MM-DD");
// Check with dates above
var rangeUsedStart = moment("2014-08-02", "YYYY-MM-DD");
var rangeUsedEnd = moment("2014-08-015", "YYYY-MM-DD");
// Range covers other ?
if((dateStart <= rangeUsedStart) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// Range intersects with other start ?
if((dateStart <= rangeUsedStart) && (rangeUsedStart <= dateEnd)) {
return false;
}
// Range intersects with other end ?
if((dateStart <= rangeUsedEnd) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// All good
return true;
Momentjs භාවිතා කරමින් කෙටි පිළිතුර :
function isOverlapping(startDate1, endDate1, startDate2, endDate2){
return moment(startDate1).isSameOrBefore(endDate2) &&
moment(startDate2).isSameOrBefore(endDate1);
}
පිළිතුර ඉහත පිළිතුරු මත පදනම් වූ නමුත් එය කෙටි කර ඇත.
Microsoft SQL SERVER - SQL ශ්රිතය තුළ
CREATE FUNCTION IsOverlapDates
(
@startDate1 as datetime,
@endDate1 as datetime,
@startDate2 as datetime,
@endDate2 as datetime
)
RETURNS int
AS
BEGIN
DECLARE @Overlap as int
SET @Overlap = (SELECT CASE WHEN (
(@startDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and end date outer
OR
(@endDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and start date outer
OR
(@startDate2 BETWEEN @startDate1 AND @endDate1) -- only one needed for outer range where dates are inside.
) THEN 1 ELSE 0 END
)
RETURN @Overlap
END
GO
--Execution of the above code
DECLARE @startDate1 as datetime
DECLARE @endDate1 as datetime
DECLARE @startDate2 as datetime
DECLARE @endDate2 as datetime
DECLARE @Overlap as int
SET @startDate1 = '2014-06-01 01:00:00'
SET @endDate1 = '2014-06-01 02:00:00'
SET @startDate2 = '2014-06-01 01:00:00'
SET @endDate2 = '2014-06-01 01:30:00'
SET @Overlap = [dbo].[IsOverlapDates] (@startDate1, @endDate1, @startDate2, @endDate2)
SELECT Overlap = @Overlap
සරලම
සරලම ක්රමය නම් දිවා කාලයේ වැඩ සඳහා හොඳින් සැලසුම් කළ පුස්තකාලයක් භාවිතා කිරීමයි.
someInterval.overlaps( anotherInterval )
ව්යාපාරයේ හොඳම දේ වන්නේ java.time
ජාවා 8 සහ පසුව සැකසූ රාමුවයි. බව එක් කරන්න ThreeTen-අමතර අතිරේක අතිරේක පන්ති java.time එම ව්යාපෘතිය, විශේෂයෙන් Interval
අප මෙහි අවශ්ය පන්තිය.
මෙම language-agnostic
ප්රශ්නයේ ටැගය සම්බන්ධයෙන් ගත් කල, ව්යාපෘති දෙකෙහිම ප්රභව කේතය වෙනත් භාෂාවලින් භාවිතා කිරීම සඳහා ලබා ගත හැකිය (ඔවුන්ගේ බලපත්ර මතක තබා ගන්න).
Interval
මෙම org.threeten.extra.Interval
පන්ති යෝග්ය වේ, නමුත් දිනය කාලීන අවස්ථා (අවශ්ය java.time.Instant
වස්තූන්) දිනය පමණක් වටිනාකම් වෙනුවට. එබැවින් අපි දිනය නිරූපණය කිරීම සඳහා යූටීසී හි දවසේ පළමු මොහොත භාවිතා කරමින් ඉදිරියට යන්නෙමු.
Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );
Interval
එම කාල පරාසය නිරූපණය කිරීම සඳහා a එකක් සාදන්න .
Interval interval_A = Interval.of( start , stop );
Interval
ආරම්භක මොහොතක් සහ a සමඟ අපට අර්ථ දැක්විය හැකිය Duration
.
Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );
අතිච්ඡාදනයන් සඳහා පරීක්ෂා කිරීම සංසන්දනය කිරීම පහසුය.
Boolean overlaps = interval_A.overlaps( interval_B );
ඔබ සන්සන්දනය කළ හැක Interval
තවත් එරෙහිව Interval
හෝ Instant
:
මෙම භාවිතය සියලු Half-Open
මුල කොහෙද කාලය කෙටි කාලයක් නිර්වචනය ප්රවේශය ඇතුළත් හා අවසානය වන සුවිශේෂී .
මෙය @ charles-bretana විසින් විශිෂ්ට පිළිතුරක් සඳහා දිගුවකි.
කෙසේ වෙතත් පිළිතුර විවෘත, සංවෘත සහ අර්ධ විවෘත (හෝ අඩක් වසා ඇති) අන්තරයන් අතර වෙනසක් නොදක්වයි.
1 වන අවස්ථාව : A, B යනු සංවෘත කාල පරතරයන් ය
A = [StartA, EndA]
B = [StartB, EndB]
[---- DateRange A ------] (True if StartA > EndB)
[--- Date Range B -----]
[---- DateRange A -----] (True if EndA < StartB)
[--- Date Range B ----]
Iff අතිච්ඡාදනය කරන්න: (StartA <= EndB) and (EndA >= StartB)
2 වන අවස්ථාව : A, B යනු විවෘත කාල පරතරයන් ය
A = (StartA, EndA)
B = (StartB, EndB)
(---- DateRange A ------) (True if StartA >= EndB)
(--- Date Range B -----)
(---- DateRange A -----) (True if EndA <= StartB)
(--- Date Range B ----)
Iff අතිච්ඡාදනය කරන්න: (StartA < EndB) and (EndA > StartB)
3 වන අවස්ථාව : A, B හරියටම විවෘතයි
A = [StartA, EndA)
B = [StartB, EndB)
[---- DateRange A ------) (True if StartA >= EndB)
[--- Date Range B -----)
[---- DateRange A -----) (True if EndA <= StartB)
[--- Date Range B ----)
අතිච්ඡාදනය තත්වය: (StartA < EndB) and (EndA > StartB)
4 වන අවස්ථාව : A, B විවෘතව පවතී
A = (StartA, EndA]
B = (StartB, EndB]
(---- DateRange A ------] (True if StartA >= EndB)
(--- Date Range B -----]
(---- DateRange A -----] (True if EndA <= StartB)
(--- Date Range B ----]
අතිච්ඡාදනය තත්වය: (StartA < EndB) and (EndA > StartB)
5 වන අවස්ථාව : දකුණු විවෘත, බී වසා ඇත
A = [StartA, EndA)
B = [StartB, EndB]
[---- DateRange A ------) (True if StartA > EndB)
[--- Date Range B -----]
[---- DateRange A -----) (True if EndA <= StartB)
[--- Date Range B ----]
අතිච්ඡාදනය තත්වය: (StartA <= EndB) and (EndA > StartB)
etc ...
අවසාන වශයෙන්, අතිච්ඡාදනය වීමට අන්තරයන් දෙකක් සඳහා පොදු කොන්දේසිය වේ
(StartA <EndB) සහ (EndA> StartB)
ඇතුළත් කළ අන්ත ලක්ෂ්ය දෙකක් අතර සංසන්දනය කරන සෑම අවස්ථාවකදීම දැඩි අසමානතාවයක් දැඩි නොවන බවට පරිවර්තනය කරයි.
ඔබ තවම අවසන් වී නැති දින පරාසයක් භාවිතා කරන්නේ නම් (තවමත් සිදුවෙමින් පවතී) උදා: endDate = '0000-00-00' සකසා නැත 0000-00-00 වලංගු දිනයක් නොවන නිසා ඔබට BETWEEN භාවිතා කළ නොහැක!
මම මෙම විසඳුම භාවිතා කළෙමි:
(Startdate BETWEEN '".$startdate2."' AND '".$enddate2."') //overlap: starts between start2/end2
OR (Startdate < '".$startdate2."'
AND (enddate = '0000-00-00' OR enddate >= '".$startdate2."')
) //overlap: starts before start2 and enddate not set 0000-00-00 (still on going) or if enddate is set but higher then startdate2
ආරම්භක දිනය 2 වැඩි නම් අවසන් දිනය අතිච්ඡාදනය නොවේ!
පිළිතුර මට ඉතා සරල බැවින් පුද්ගලයෙකුට අතිච්ඡාදනය වන දිනයන් තිබේදැයි බැලීමට වඩාත් සාමාන්ය ගතික SQL ප්රකාශයක් මම නිර්මාණය කර ඇත්තෙමි.
SELECT DISTINCT T1.EmpID
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.EmpID = T2.EmpID
AND T1.JobID <> T2.JobID
AND (
(T1.DateFrom >= T2.DateFrom AND T1.dateFrom <= T2.DateTo)
OR (T1.DateTo >= T2.DateFrom AND T1.DateTo <= T2.DateTo)
OR (T1.DateFrom < T2.DateFrom AND T1.DateTo IS NULL)
)
AND NOT (T1.DateFrom = T2.DateFrom)
Ret බ්රෙටානා විසින් දෙන ලද ගණිතමය විසඳුම හොඳයි, නමුත් නිශ්චිත තොරතුරු දෙකක් නොසලකා හරියි:
සංවෘත හෝ විවෘත කාල පරතරයන් ගැන, retBretana හි විසඳුම සංවෘත කාල පරාසයන් සඳහා වලංගු වේ
(StartA <= EndB) සහ (EndA> = StartB)
අර්ධ විවෘත කාල පරතරයන් සඳහා නැවත ලිවිය හැකිය :
(StartA <EndB) සහ (EndA> StartB)
මෙම නිවැරදි කිරීම අවශ්ය වන්නේ විවෘත කාල පරතරයක් අර්ථ දැක්වීම අනුව අන්තරයක අගය පරාසයට අයත් නොවන බැවිනි.
හිස් කාල පරතරයන් ගැන , හොඳයි, මෙහි ඉහත පෙන්වා ඇති සම්බන්ධතාවය නොපවතී. අර්ථ දැක්වීම අනුව වලංගු අගයක් නොමැති හිස් කාල පරතරයන් විශේෂ අවස්ථාවක් ලෙස හැසිරවිය යුතුය. මෙම උදාහරණය හරහා මම මගේ ජාවා කාල පුස්තකාලය Time4J මගින් නිරූපණය කරමි :
MomentInterval a = MomentInterval.between(Instant.now(), Instant.now().plusSeconds(2));
MomentInterval b = a.collapse(); // make b an empty interval out of a
System.out.println(a); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:13,909000000Z)
System.out.println(b); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:11,909000000Z)
ප්රමුඛ චතුරස්ර වරහන "[" සංවෘත ආරම්භයක් පෙන්නුම් කරන අතර අවසාන වරහන ")" විවෘත අවසානයක් දක්වයි.
System.out.println(
"startA < endB: " + a.getStartAsInstant().isBefore(b.getEndAsInstant())); // false
System.out.println(
"endA > startB: " + a.getEndAsInstant().isAfter(b.getStartAsInstant())); // true
System.out.println("a overlaps b: " + a.intersects(b)); // a overlaps b: false
ඉහත පෙන්වා ඇති පරිදි, හිස් අන්තරයන් ඉහත අතිච්ඡාදනය කොන්දේසිය උල්ලං late නය කරයි (විශේෂයෙන් ආරම්භක <endB), එබැවින් හිස් අන්තරයක් සමඟ ඕනෑම අත්තනෝමතික පරතරයක් අතිච්ඡාදනය වන බව සහතික කිරීම සඳහා ටයිම් 4 ජේ (සහ අනෙකුත් පුස්තකාල ද) එය විශේෂ අද්දර නඩුවක් ලෙස හැසිරවිය යුතුය. නොපවතී. ඇත්ත වශයෙන්ම, දින පරතරයන් (ටයිම් 4 ජේ හි පෙරනිමියෙන් වසා ඇති නමුත් හිස් දින කාල පරතරයන් මෙන් අඩක් විවෘත විය හැකිය) ඒ හා සමාන ආකාරයකින් හසුරුවනු ලැබේ.
දේශීයව ප්රයෝජනවත් විය හැකි සාමාන්ය ක්රමයක් මෙන්න.
// Takes a list and returns all records that have overlapping time ranges.
public static IEnumerable<T> GetOverlappedTimes<T>(IEnumerable<T> list, Func<T, bool> filter, Func<T,DateTime> start, Func<T, DateTime> end)
{
// Selects all records that match filter() on left side and returns all records on right side that overlap.
var overlap = from t1 in list
where filter(t1)
from t2 in list
where !object.Equals(t1, t2) // Don't match the same record on right side.
let in1 = start(t1)
let out1 = end(t1)
let in2 = start(t2)
let out2 = end(t2)
where in1 <= out2 && out1 >= in2
let totover = GetMins(in1, out1, in2, out2)
select t2;
return overlap;
}
public static void TestOverlap()
{
var tl1 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 1:00pm".ToDate(), Out = "1/1/08 4:00pm".ToDate() };
var tl2 = new TempTimeEntry() { ID = 2, Name = "John", In = "1/1/08 5:00pm".ToDate(), Out = "1/1/08 6:00pm".ToDate() };
var tl3 = new TempTimeEntry() { ID = 3, Name = "Lisa", In = "1/1/08 7:00pm".ToDate(), Out = "1/1/08 9:00pm".ToDate() };
var tl4 = new TempTimeEntry() { ID = 4, Name = "Joe", In = "1/1/08 3:00pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
var tl5 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 8:01pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
var list = new List<TempTimeEntry>() { tl1, tl2, tl3, tl4, tl5 };
var overlap = GetOverlappedTimes(list, (TempTimeEntry t1)=>t1.ID==1, (TempTimeEntry tIn) => tIn.In, (TempTimeEntry tOut) => tOut.Out);
Console.WriteLine("\nRecords overlap:");
foreach (var tl in overlap)
Console.WriteLine("Name:{0} T1In:{1} T1Out:{2}", tl.Name, tl.In, tl.Out);
Console.WriteLine("Done");
/* Output:
Records overlap:
Name:Joe T1In:1/1/2008 3:00:00 PM T1Out:1/1/2008 8:00:00 PM
Name:Lisa T1In:1/1/2008 7:00:00 PM T1Out:1/1/2008 9:00:00 PM
Done
*/
}
public static class NumberExtensionMethods
{
public static Boolean IsBetween(this Int64 value, Int64 Min, Int64 Max)
{
if (value >= Min && value <= Max) return true;
else return false;
}
public static Boolean IsBetween(this DateTime value, DateTime Min, DateTime Max)
{
Int64 numricValue = value.Ticks;
Int64 numericStartDate = Min.Ticks;
Int64 numericEndDate = Max.Ticks;
if (numricValue.IsBetween(numericStartDate, numericEndDate) )
{
return true;
}
return false;
}
}
public static Boolean IsOverlap(DateTime startDate1, DateTime endDate1, DateTime startDate2, DateTime endDate2)
{
Int64 numericStartDate1 = startDate1.Ticks;
Int64 numericEndDate1 = endDate1.Ticks;
Int64 numericStartDate2 = startDate2.Ticks;
Int64 numericEndDate2 = endDate2.Ticks;
if (numericStartDate2.IsBetween(numericStartDate1, numericEndDate1) ||
numericEndDate2.IsBetween(numericStartDate1, numericEndDate1) ||
numericStartDate1.IsBetween(numericStartDate2, numericEndDate2) ||
numericEndDate1.IsBetween(numericStartDate2, numericEndDate2))
{
return true;
}
return false;
}
if (IsOverlap(startdate1, enddate1, startdate2, enddate2))
{
Console.WriteLine("IsOverlap");
}
Java util.Date භාවිතා කරමින්, මෙන්න මම කළ දේ.
public static boolean checkTimeOverlaps(Date startDate1, Date endDate1, Date startDate2, Date endDate2)
{
if (startDate1 == null || endDate1 == null || startDate2 == null || endDate2 == null)
return false;
if ((startDate1.getTime() <= endDate2.getTime()) && (startDate2.getTime() <= endDate1.getTime()))
return true;
return false;
}
මගේ මතය අනුව එය කිරීමට ඇති පහසුම ක්රමය වනුයේ එන්ඩ්ඩේට් 1 ස්ටාර්ට් ඩේට් 2 ට පෙර ද එන්ඩ් ඩේට් 2 ස්ටාර්ට් ඩේට් 1 ට පෙර ද යන්න සංසන්දනය කිරීමයි.
ඇත්ත වශයෙන්ම ඔබ එන්ඩ්ඩේට පෙර ආරම්භක දිනය සැමවිටම පවතින කාල පරතරයන් සලකා බලන්නේ නම්.
මට කාල වේලාවන් වෙනුවට දින වකවානු ඇති තත්වයක් මට ඇති අතර, දිනයන් අතිච්ඡාදනය විය හැක්කේ ආරම්භක / අවසානයේ පමණි. පහත උදාහරණය:
(කොළ යනු වර්තමාන පරතරයයි, නිල් කුට්ටි වලංගු කාල පරතරයන් වේ, රතු ඒවා අතිච්ඡාදනය වේ).
මම පහත විසඳුමට ඉයන් නෙල්සන්ගේ පිළිතුර අනුගත කළෙමි:
(startB <= startA && endB > startA)
|| (startB >= startA && startB < endA)
මෙය සියලු අතිච්ඡාදන අවස්ථාවන්ට ගැලපෙන නමුත් අවසර ලත් අතිච්ඡාදනයන් නොසලකා හරියි.
ගැටලුව නඩු වලට බෙදන්න, ඉන්පසු එක් එක් සිද්ධිය හසුරුවන්න .
'දින පරාස දෙක එකිනෙක ගැටෙන' තත්වය අවස්ථා දෙකකින් ආවරණය වේ - පළමු දින පරාසය දෙවන සිට ආරම්භ වේ, නැතහොත් දෙවන දිනය පරාසය පළමු සිට ආරම්භ වේ.
ඔබට මෙය උත්සාහ කළ හැකිය:
//custom date for example
$d1 = new DateTime("2012-07-08");
$d2 = new DateTime("2012-07-11");
$d3 = new DateTime("2012-07-08");
$d4 = new DateTime("2012-07-15");
//create a date period object
$interval = new DateInterval('P1D');
$daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2));
$daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4));
array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange);
මෙය මගේ විසඳුමයි, අගයන් අතිච්ඡාදනය නොවන විට එය සත්ය වේ:
X START 1 Y END 1
START 2 B END 2
TEST1: (X <= A || X >= B)
&&
TEST2: (Y >= B || Y <= A)
&&
TEST3: (X >= B || Y <= A)
X-------------Y
A-----B
TEST1: TRUE
TEST2: TRUE
TEST3: FALSE
RESULT: FALSE
---------------------------------------
X---Y
A---B
TEST1: TRUE
TEST2: TRUE
TEST3: TRUE
RESULT: TRUE
---------------------------------------
X---Y
A---B
TEST1: TRUE
TEST2: TRUE
TEST3: TRUE
RESULT: TRUE
---------------------------------------
X----Y
A---------------B
TEST1: FALSE
TEST2: FALSE
TEST3: FALSE
RESULT: FALSE
රුබී සඳහා මම මෙය සොයාගතිමි
class Interval < ActiveRecord::Base
validates_presence_of :start_date, :end_date
# Check if a given interval overlaps this interval
def overlaps?(other)
(start_date - other.end_date) * (other.start_date - end_date) >= 0
end
# Return a scope for all interval overlapping the given interval, including the given interval itself
named_scope :overlapping, lambda { |interval| {
:conditions => ["id <> ? AND (DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", interval.id, interval.end_date, interval.start_date]
}}
end
හොඳ පැහැදිලි කිරීමකින් එය මෙහි හමු විය -> http://makandracards.com/makandra/984-test-if-two-date-ranges-overlap-in-ruby-or-rails
පහත දැක්වෙන විමසුම මඟින් මට ලබා දී ඇති දින පරාසය (ආරම්භක හා අවසන් දිනයන් මගේ වගු නාමයේ ඕනෑම දිනයක් (ආරම්භක හා අවසන් දිනයන්) සමඟ අතිච්ඡාදනය වේ.
select id from table_name where (START_DT_TM >= 'END_DATE_TIME' OR
(END_DT_TM BETWEEN 'START_DATE_TIME' AND 'END_DATE_TIME'))