Don't worry, dit is niet de "zoveelste" vraag om een datumdiff script, maar in plaats daarvan mijn implementatie.
Ik zocht een oplossing om 2 datums van elkaar af te trekken, en mij te vertellen (in plat Nederlands) wat er nu precies uitkwam. Ik dacht dat ik een implementatie had, en deze deed 2 datums van elkaar aftrekken, en gaf vervolgens weer hoeveel tijd er tussen de 2 datums zat.
Een voorbeeldje:
"3 jaar, 4 maanden, 3 weken, 2 dagen, 2 uur, 33 minuten en 2 seconden"
Ik kwam er echter vanmiddag achter dat mijn oude code een fout bevatte, want iemand die in 1995 geboren was, bleek ineens 2 jaar oud te zijn
.
Nu heb ik mijn oude code zo aangepast, dat er deze code is uitgekomen. Het lijkt omslachtig, en dat is ook de reden dat ik hem hier plaats, in de hoop dat ik er niet alleen mensen een hoop "zoekwerk" mee uit handen neem, maar ook dat er een paar kritische code kloppers naar mijn code kunnen kijken.
Allereerst mijn oude implementatie, misschien kunnen jullie er iets mee.
Bovenstaande code maakt gebruik van een tweetal functies waarvan ik er maar 1 geef, die ander doet namelijk niets anders dan een (string) datum omzetten naar een UNIX integer. Ga er even vanuit dat deze werkt en een int teruggeeft.
Maar goed, hieronder staat de nieuwe implementatie.
Maar goed, wat wil ik hiermee bereiken? Misschien een stukje code review
en natuurlijk dat ik er andere mee help
. Je zou bovenstaande code kunnen gebruiken door zoiets te doen:
Natuurlijk ben ik in staat om vragen te beantwoorden en ik hoop ook dat er mensen zijn die serieuze input hebben!
Ik zocht een oplossing om 2 datums van elkaar af te trekken, en mij te vertellen (in plat Nederlands) wat er nu precies uitkwam. Ik dacht dat ik een implementatie had, en deze deed 2 datums van elkaar aftrekken, en gaf vervolgens weer hoeveel tijd er tussen de 2 datums zat.
Een voorbeeldje:
"3 jaar, 4 maanden, 3 weken, 2 dagen, 2 uur, 33 minuten en 2 seconden"
Ik kwam er echter vanmiddag achter dat mijn oude code een fout bevatte, want iemand die in 1995 geboren was, bleek ineens 2 jaar oud te zijn

Nu heb ik mijn oude code zo aangepast, dat er deze code is uitgekomen. Het lijkt omslachtig, en dat is ook de reden dat ik hem hier plaats, in de hoop dat ik er niet alleen mensen een hoop "zoekwerk" mee uit handen neem, maar ook dat er een paar kritische code kloppers naar mijn code kunnen kijken.
Allereerst mijn oude implementatie, misschien kunnen jullie er iets mee.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
| /** * Geeft $str1 terug indien $val gelijk is aan 1, anders (indien $val groter is dan 1 of gelijk is aan 0) gaat $str2 terug. */ function addSingleMultiple($intVal, $strSingle, $strMultiple, $blnSkip=false) { if ($blnSkip && ($intVal == 0)) { return ''; } else { return $intVal.' '.(($intVal == 1) ? $strSingle : $strMultiple).', '; } } /** * Trekt 2 data van elkaar af en geeft het resultaat terug als een string. * * @param string Datum die afgetrokken zal worden van $date2. * @param string Datum waarvan $date1 afgetrokken zal worden. * @return string String met het verschil uitgeschreven als een string, bijv: "1 jaar, 0 maanden, 3 weken, 2 dagen, 1 uur, 2 minuten, 3 seconden". */ function dateDiff($intStart, $intEnd) { // // Constants $intDay = 86400; $intHour = 3600; $intMinute = 60; // // Variables $intStart = parseDateTime($intStart); $intEnd = parseDateTime($intEnd); $intDateDiff = $intEnd - $intStart; $arrResult = array(); // // Init $arrResult['past'] = ($intDateDiff < 0) ? true : false; $intDateDiff = $arrResult['past'] ? $intDateDiff * -1 : $intDateDiff; // // Verschillen berekenen $arrResult['diff']['days'] = floor($intDateDiff / $intDay); $arrResult['diff']['hours'] = floor($intDateDiff / $intHour); $arrResult['diff']['minutes'] = floor($intDateDiff / $intMinute); $arrResult['diff']['seconds'] = $intDateDiff; // // De rest doen $intI = $intDateDiff; $intN = intval($intI / 60); $intI = $intI % 60; $intH = intval($intN / 60); $intN = $intN % 60; $intD = intval($intH / 24); $intH = $intH % 24; $intW = intval($intD / 7); $intD = $intD % 7; // // Maanden tellen $intM = 0; $intOffset = 0; $intTempStart = $arrResult['past'] ? $intEnd : $intStart; $intTempEnd = $arrResult['past'] ? $intStart : $intEnd; $intCurrent = $intOld = $intTempStart; while ($intCurrent < $intTempEnd) { $intOffset++; $intCurrent = strtotime("+1 weeks", $intCurrent); if ( ( (adodb_date('m', $intCurrent) > adodb_date('m', $intOld)) || (adodb_date('Y', $intCurrent) != adodb_date('Y', $intOld)) ) && (adodb_date('d', $intCurrent) > adodb_date('d', $intTempStart)) ) { $intM++; $intW-= $intOffset; $intOffset = 0; $intOld = $intCurrent; } } // // Nieuwe dagen berekenen if ($intM > 0) { $intTemp = $intTempEnd - strtotime('+'.$intM.' months +'.$intW.' weeks ', $intTempStart); $intD = intval($intTemp / $intDay); } // // Jaartal berekenen $intY = intval($intM / 12); // // Invullen $arrResult['diff']['months'] = $intM; $arrResult['diff']['years'] = $intY; $arrResult['text']['seconds'] = $intI; $arrResult['text']['minutes'] = $intN; $arrResult['text']['hours'] = $intH; $arrResult['text']['days'] = $intD; $arrResult['text']['weeks'] = $intW; $arrResult['text']['months'] = $intM; $arrResult['text']['years'] = $intY; // // String samenstellen $strTemp = addSingleMultiple($intY, 'jaar', 'jaren', true); $strTemp.= addSingleMultiple($intM, 'maand', 'maanden', true); $strTemp.= addSingleMultiple($intW, 'week', 'weken', true); $strTemp.= addSingleMultiple($intD, 'dag', 'dagen', true); $strTemp.= addSingleMultiple($intH, 'uur', 'uren', true); $strTemp.= addSingleMultiple($intN, 'minuut', 'minuten', true); $strTemp.= addSingleMultiple($intI, 'seconde', 'seconden', true); $strTemp = substr($strTemp, 0, strlen($strTemp) - 2); $arrResult['text']['string'] = $strTemp; if (strpos($strTemp, ',')) { $arrResult['text']['string'] = substr($strTemp, 0, strrpos($strTemp, ",")); if ($arrResult['text']['string'] != '') { $arrResult['text']['string'].= ' en '; } $arrResult['text']['string'].= substr($strTemp, strrpos($strTemp, ",") + 1); } // // Eind tijd samenstellen $arrResult['start'] = $intStart; $arrResult['end'] = $intEnd; // // Klaar return $arrResult; } |
Bovenstaande code maakt gebruik van een tweetal functies waarvan ik er maar 1 geef, die ander doet namelijk niets anders dan een (string) datum omzetten naar een UNIX integer. Ga er even vanuit dat deze werkt en een int teruggeeft.
Maar goed, hieronder staat de nieuwe implementatie.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
| /** * Trekt 2 data van elkaar af en geeft het resultaat terug als een string. * * @param string Datum die afgetrokken zal worden van $date2. * @param string Datum waarvan $date1 afgetrokken zal worden. * @return string String met het verschil uitgeschreven als een string, bijv: "1 jaar, 0 maanden, 3 weken, 2 dagen, 1 uur, 2 minuten, 3 seconden". */ function dateDiff($intStart, $intEnd) { // // Start en einddatum naar UNIX omzetten $intStart = parseDateTime($intStart); $intEnd = parseDateTime($intEnd); if (!$intStart || !$intEnd) { return false; } // // Juiste berekening gegens nu pakken, zodat we niet continu met -1 hoeven te rekenen if ($intStart > $intEnd) { $intCalcStart = $intEnd; $intCalcEnd = $intStart; } else { $intCalcStart = $intStart; $intCalcEnd = $intEnd; } // // Initializeren van result array $arrResult = array(); $arrResult['start'] = $intCalcStart; $arrResult['end'] = $intCalcEnd; $arrResult['past'] = ($intStart > $intEnd) ? true : false; // // En vervolgens berekenen $arrResult['totals']['year'] = adodb_date('Y', $intCalcEnd) - adodb_date('Y', $intCalcStart); $arrResult['totals']['month'] = adodb_date('m', $intCalcEnd) - adodb_date('m', $intCalcStart) + ($arrResult['totals']['year'] * 12); $arrResult['totals']['week'] = adodb_date('W', $intCalcEnd) - adodb_date('W', $intCalcStart) + ($arrResult['totals']['year'] * 52); // from PHP 4.1 $arrResult['totals']['day'] = adodb_date('z', $intCalcEnd) - adodb_date('z', $intCalcStart) + (((int)adodb_date('L', $intCalcStart)) ? ($arrResult['totals']['year'] * 366) : ($arrResult['totals']['year'] * 365)); $arrResult['totals']['hour'] = $arrResult['totals']['day'] * 24; $arrResult['totals']['minute'] = $arrResult['totals']['hour'] * 60; $arrResult['totals']['second'] = ($intCalcEnd - $intCalcStart); // // Negatieve waardes omvormen foreach ($arrResult['totals'] as $strKey => $intValue) { // // Indien dit deel ervoor zorgt dat we eerder dan de doeldatum uitkomen, klopt er iets niet! // Er moet namelijk iets over te houden zijn ;) if (strtotime($intValue.' '.$strKey.'s', $arrResult['start']) > $arrResult['end']) { $intValue+= ($intValue < 0) ? 1 : -1; } // // Make sure it is acurate if ($intValue < 0) { $intValue = $intValue * -1; } $arrResult['totals'][$strKey] = $intValue; } // // Aantal jaren en maanden berekenen $arrResult['diff']['year'] = $arrResult['totals']['year']; $arrResult['diff']['month'] = ($arrResult['totals']['month'] > 11) ? ($arrResult['totals']['month'] - ($arrResult['totals']['year'] * 12)) : $arrResult['totals']['month']; // // Tijd die nog over is (in seconden), tot aan de andere datum berekenen $intCalcDate = $intCalcEnd - strtotime('+'.$arrResult['diff']['year'].' years +'.$arrResult['diff']['month'].' months', $intCalcStart); // // Week berekenen $arrResult['diff']['week'] = floor(($intCalcDate / 86400) / 7); $intCalcDate-= ($arrResult['diff']['week'] * 7) * 86400; // // Dagen berekenen $arrResult['diff']['day'] = floor($intCalcDate / 86400); $intCalcDate-= $arrResult['diff']['day'] * 86400; // // Uren berekenen $arrResult['diff']['hour'] = floor($intCalcDate / 3600); $intCalcDate-= $arrResult['diff']['hour'] * 3600; // // Minuten berekenen $arrResult['diff']['minute'] = floor($intCalcDate / 60); $intCalcDate-= $arrResult['diff']['minute'] * 60; // // Seconden berekenen $arrResult['diff']['second'] = $intCalcDate; // // String samenstellen $strTemp = addSingleMultiple($arrResult['diff']['year'], 'jaar', 'jaren', true); $strTemp.= addSingleMultiple($arrResult['diff']['month'], 'maand', 'maanden', true); $strTemp.= addSingleMultiple($arrResult['diff']['week'], 'week', 'weken', true); $strTemp.= addSingleMultiple($arrResult['diff']['day'], 'dag', 'dagen', true); $strTemp.= addSingleMultiple($arrResult['diff']['hour'], 'uur', 'uren', true); $strTemp.= addSingleMultiple($arrResult['diff']['minute'], 'minuut', 'minuten', true); $strTemp.= addSingleMultiple($arrResult['diff']['second'], 'seconde', 'seconden', true); $strTemp = substr($strTemp, 0, strlen($strTemp) - 2); $arrResult['text']['string'] = $strTemp; if (strpos(',', $strTemp)) { $arrResult['text']['string'] = substr($strTemp, 0, strrpos($strTemp, ",")); if ($arrResult['text']['string'] != '') { $arrResult['text']['string'].= ' en '; } $arrResult['text']['string'].= substr($strTemp, strrpos($strTemp, ",") + 1); } // // Klaar return $arrResult; } |
Maar goed, wat wil ik hiermee bereiken? Misschien een stukje code review
PHP:
1
| print_r(dateDiff(adodb_date('d-m-Y'), strtotime("-3 years"))); |
Natuurlijk ben ik in staat om vragen te beantwoorden en ik hoop ook dat er mensen zijn die serieuze input hebben!