PluginProbe
ShiftController Employee Shift Scheduling / 4.9.92
ShiftController Employee Shift Scheduling v4.9.92
4.9.97 4.9.96 4.9.95 4.9.74 4.9.75 4.9.76 4.9.77 4.9.78 4.9.84 4.9.85 4.9.87 4.9.91 4.9.92 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 3.2.4 All 38 releases
shiftcontroller / hc3 / time.php

time.php in ShiftController Employee Shift Scheduling 4.9.92, at hc3/time.php

848 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if (! defined('ABSPATH')) exit; // Exit if accessed directly
2 interface HC3_ITime
3 {
4 public function setTimezone( $tz );
5 public function setNow();
6 public function formatToDatepicker();
7 public function formatDate( $format = '' );
8 public function formatDateWithWeekday( $format = '' );
9 public function formatDateDb();
10 public function setDateDb( $date );
11 public function setDateTimeDb( $datetime );
12 public function formatTime();
13 public function formatDateTimeDb();
14 public function formatTimeDb();
15 public function setStartDay();
16 public function getWeekStartsOn();
17 public function setStartWeek();
18 public function setStartMonth();
19 public function setEndMonth();
20 public function setStartYear();
21 public function setEndYear();
22 public function setEndWeek();
23 public function getYear();
24 public function getDay();
25 public function getWeekday();
26 public function getMonthName();
27 public function getWeekdayName();
28 public function formatDateRange( $date1, $date2, $with_weekday = FALSE );
29 public function getMonthMatrix( $skipWeekdays = array() );
30 public function getParts();
31 public function getWeekdays();
32 public function sortWeekdays( $wds );
33 public function formatDuration( $seconds );
34 public function getTimeInDay();
35 }
36
37 class HC3_Time extends DateTime implements HC3_ITime
38 {
39 public $timeFormat = 'g:ia';
40 public $dateFormat = 'j M Y';
41 public $weekStartsOn = 0;
42
43 protected $_months = array();
44 protected $_weekdays = array();
45
46 var $timezone = '';
47
48 function __construct( ?HC3_Settings $settings = NULL )
49 {
50 parent::__construct();
51
52 $localiseThis = array('__Jan__', '__Feb__', '__Mar__', '__Apr__', '__May__', '__Jun__', '__Jul__', '__Aug__', '__Sep__', '__Oct__', '__Nov__', '__Dec__');
53
54 $this->_months = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
55 $this->_weekdays = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
56
57 if( $settings ){
58 if( $time_format = $settings->get('datetime_time_format') ){
59 $this->timeFormat = $time_format;
60 }
61 if( $date_format = $settings->get('datetime_date_format') ){
62 $this->dateFormat = $date_format;
63 }
64 if( $week_starts = $settings->get('datetime_week_starts') ){
65 $this->weekStartsOn = $week_starts;
66 }
67
68 $tz = '';
69
70 $tz = $settings->get('datetime_timezone');
71 if( ! $tz ){
72 $tz = '';
73 }
74 $tz = trim( $tz );
75
76 if( ! strlen($tz) ){
77 $tz = $this->getDefaultTimezone();
78 $tz = trim( $tz );
79 }
80
81 if( strlen($tz) ){
82 $this->setTimezone( $tz );
83 }
84 }
85
86 // if( defined('WPINC') ){
87 // $tz = get_option('timezone_string');
88 // if( ! strlen($tz) ){
89 // $offset = get_option('gmt_offset');
90 // if( $offset ){
91 // $tz = 'Etc/GMT';
92 // if( $offset > 0 ){
93 // $tz .= '+' . $offset;
94 // }
95 // else {
96 // $tz .= '-' . -$offset;
97 // }
98 // }
99 // }
100
101 // $this->setTimezone( $tz );
102 // }
103 }
104
105 #[\ReturnTypeWillChange]
106 public function setTimezone( $tz )
107 {
108 if( is_array($tz) )
109 $tz = $tz[0];
110
111 if( ! $tz )
112 $tz = date_default_timezone_get();
113
114 // check timezone
115 $timezones = $this->getTimezones();
116
117 if( isset($timezones[$tz]) OR ('UTC' == $tz) ){
118 $this->timezone = $tz;
119 $tz = new DateTimeZone( $tz );
120 parent::setTimezone( $tz );
121 }
122 }
123
124 public function setNow()
125 {
126 $this->setTimestamp( time() );
127 return $this;
128 }
129
130 public function formatToDatepicker()
131 {
132 $dateFormat = $this->dateFormat;
133
134 $pattern = array(
135 //day
136 'd', //day of the month
137 'j', //3 letter name of the day
138 'l', //full name of the day
139 'z', //day of the year
140
141 //month
142 'F', //Month name full
143 'M', //Month name short
144 'n', //numeric month no leading zeros
145 'm', //numeric month leading zeros
146
147 //year
148 'Y', //full numeric year
149 'y' //numeric year: 2 digit
150 );
151
152 $replace = array(
153 'dd','d','DD','o',
154 'MM','M','m','mm',
155 'yyyy','y'
156 );
157 foreach($pattern as &$p){
158 $p = '/'.$p.'/';
159 }
160 return preg_replace( $pattern, $replace, $dateFormat );
161 }
162
163 public function formatDateWithWeekday( $format = '' )
164 {
165 $out = array();
166 $out[] = $this->getWeekdayName();
167 $out[] = $this->formatDate( $format );
168 $out = join(', ', $out);
169 return $out;
170 }
171
172 public function formatDate( $format = '' )
173 {
174 if( ! strlen($format) ){
175 $format = $this->dateFormat;
176 }
177
178 $return = $this->format( $format );
179
180 // replace English months to localized ones
181 $replace_from = array();
182 $replace_to = array();
183 foreach( $this->_months as $month ){
184 $replace_from[] = $month;
185 $replace_to[] = '__' . $month . '__';
186 }
187
188 $return = str_replace( $replace_from, $replace_to, $return );
189 return $return;
190 }
191
192 public function formatDateDb()
193 {
194 $dateFormat = 'Ymd';
195 $return = $this->format( $dateFormat );
196 return $return;
197 }
198
199 public function setDateDb( $date )
200 {
201 list( $year, $month, $day ) = $this->_splitDate( $date );
202 $year = (int) $year;
203 $month = (int) $month;
204 $day = (int) $day;
205
206 $this->setDate( $year, $month, $day );
207 $this->setTime( 0, 0, 0 );
208 return $this;
209 }
210
211 public function setDateTimeDb( $datetime )
212 {
213 $date = substr($datetime, 0, 8);
214 $this->setDateDb( $date );
215
216 $hours = substr($datetime, 8, 2);
217 $minutes = substr($datetime, 10, 2);
218
219 $hours = (int) $hours;
220 $minutes = (int) $minutes;
221
222 $this->setTime( $hours, $minutes, 0 );
223
224 return $this;
225 }
226
227 public function formatTime( $format = NULL )
228 {
229 if( NULL === $format ) $format = $this->timeFormat;
230
231 if( '12short' === $format ){
232 $ret = $this->format( 'g:ia' );
233 $ret = str_replace( ':00', '', $ret );
234 }
235 elseif( '12xshort' === $format ){
236 $ret = $this->format( 'g:ia' );
237 $ret = str_replace( 'am', 'a', $ret );
238 $ret = str_replace( 'pm', 'p', $ret );
239 $ret = str_replace( ':00', '', $ret );
240 }
241 elseif( '24short' === $format ){
242 $ret = $this->format( 'H:i' );
243 $ret = preg_replace( '/0(\d\:)/', '${1}', $ret );
244 $ret = str_replace( ':00', '', $ret );
245 }
246 else {
247 $ret = $this->format( $format );
248 }
249
250 return $ret;
251 }
252
253 protected function _splitDate( $string )
254 {
255 $year = substr( $string, 0, 4 );
256 $month = substr( $string, 4, 2 );
257 $day = substr( $string, 6, 4 );
258 $return = array( $year, $month, $day );
259 return $return;
260 }
261
262 public function formatDateTimeDb()
263 {
264 $date = $this->formatDateDb();
265 $time = $this->formatTimeDb();
266 $return = $date . $time;
267 return $return;
268 }
269
270 public function formatTimeDb()
271 {
272 $h = $this->format('G');
273 $m = $this->format('i');
274
275 $h = str_pad( $h, 2, 0, STR_PAD_LEFT );
276 $m = str_pad( $m, 2, 0, STR_PAD_LEFT );
277
278 $return = $h . $m;
279 return $return;
280 }
281
282 public function setStartDay()
283 {
284 $this->setTime( 0, 0, 0 );
285 return $this;
286 }
287
288 public function setEndDay()
289 {
290 $this->setTime( 23, 59, 0 );
291 return $this;
292 }
293
294 public function getTimeInDay()
295 {
296 $dateTimeDb = $this->formatDateTimeDb();
297 // 202404042030
298
299 $hourString = substr( $dateTimeDb, 8, 2 );
300 $minuteString = substr( $dateTimeDb, 10, 2 );
301
302 $h = (int) $hourString;
303 $m = (int) $minuteString;
304
305 $ret = 60 * 60 * $h + 60 * $m;
306
307 return $ret;
308 }
309
310 public function getWeekStartsOn()
311 {
312 return $this->weekStartsOn;
313 }
314
315 public function setStartWeek()
316 {
317 $this->setStartDay();
318 $weekDay = $this->getWeekday();
319
320 while( $weekDay != $this->weekStartsOn ){
321 $this->modify( '-1 day' );
322 $weekDay = $this->getWeekday();
323 }
324
325 return $this;
326 }
327
328 public function setStartMonth()
329 {
330 $year = $this->format('Y');
331 $month = $this->format('m');
332 $day = '01';
333
334 $date = $year . $month . $day;
335 $this->setDateDb( $date );
336 $this->setTime( 0, 0, 0 );
337
338 return $this;
339 }
340
341 public function setEndMonth()
342 {
343 $this->modify('+1 month');
344
345 $year = $this->format('Y');
346 $month = $this->format('m');
347 $day = '01';
348
349 $date = $year . $month . $day;
350 $this->setDateDb( $date );
351 $this->modify('-1 day')
352 ->setEndDay()
353 ;
354
355 return $this;
356 }
357
358 public function setStartYear()
359 {
360 $year = $this->format('Y');
361 $month = '01';
362 $day = '01';
363
364 $date = $year . $month . $day;
365 $this->setDateDb( $date );
366 $this->setTime( 0, 0, 0 );
367
368 return $this;
369 }
370
371 public function setEndYear()
372 {
373 $this->modify('+1 year');
374
375 $year = $this->format('Y');
376 $month = '01';
377 $day = '01';
378
379 $date = $year . $month . $day;
380 $this->setDateDb( $date );
381 $this->modify('-1 day')
382 ->setEndDay()
383 ;
384
385 return $this;
386 }
387
388 public function setEndWeek()
389 {
390 $this->setStartDay();
391 $this->modify( '+1 day' );
392 $weekDay = $this->getWeekday();
393
394 while( $weekDay != $this->weekStartsOn ){
395 $this->modify( '+1 day' );
396 $weekDay = $this->getWeekday();
397 }
398
399 $this->modify( '-1 day' )
400 ->setEndDay()
401 ;
402
403 return $this;
404 }
405
406 public function getYear()
407 {
408 $return = $this->format('Y');
409 return $return;
410 }
411
412 public function getDay()
413 {
414 $return = $this->format('j');
415 return $return;
416 }
417
418 public function getWeekday()
419 {
420 $return = $this->format('w');
421 return $return;
422 }
423
424 public function getWeekNo()
425 {
426 $return = $this->format('W'); // but it works out of the box for week starts on monday
427 $weekday = $this->getWeekday();
428 if( ! $weekday ){ // sunday
429 if( ! $this->weekStartsOn ){
430 $return = $return + 1;
431 }
432 }
433 return $return;
434 }
435
436 public function getMonthName()
437 {
438 $month = $this->format('n') - 1;
439 $return = $this->_months[$month];
440 $return = '__' . $return . '__';
441 return $return;
442 }
443
444 public function getWeekdayName()
445 {
446 $wd = $this->getWeekday();
447 $return = $this->_weekdays[$wd];
448 $return = '__' . $return . '__';
449 return $return;
450 }
451
452 public function formatDateRange( $date1, $date2, $with_weekday = FALSE )
453 {
454 list( $start_date_view, $end_date_view ) = $this->_formatDateRange( $date1, $date2, $with_weekday );
455
456 if( $end_date_view ){
457 $return = $start_date_view . ' - ' . $end_date_view;
458 }
459 else {
460 $return = $start_date_view;
461 }
462 return $return;
463 }
464
465 protected function _formatDateRange( $date1, $date2, $with_weekday = FALSE )
466 {
467 $return = array();
468 $skip = array();
469
470 if( $date1 == $date2 ){
471 $this->setDateDb( $date1 );
472 $view_date1 = $this->formatDate();
473 if( $with_weekday ){
474 $view_date1 = $this->formatWeekdayShort() . ', ' . $view_date1;
475 }
476 $return[] = $view_date1;
477 $return[] = NULL;
478 return $return;
479 }
480
481 $this->setDateDb( $date1 );
482 $year1 = $this->getYear();
483 $month1 = $this->format('n');
484
485 $this->setDateDb( $date2 );
486 $year2 = $this->getYear();
487 $month2 = $this->format('n');
488
489 if( $year2 == $year1 )
490 $skip['year'] = TRUE;
491 if( ($year2 == $year1) && ($month2 == $month1) )
492 $skip['month'] = TRUE;
493
494 if( $skip ){
495 $date_format = $this->dateFormat;
496 $date_format_short = $date_format;
497
498 $tags = array('m', 'n', 'M');
499 foreach( $tags as $t ){
500 $pos_m_original = strpos($date_format_short, $t);
501 if( $pos_m_original !== FALSE )
502 break;
503 }
504
505 if( isset($skip['year']) ){
506 $pos_y = strpos($date_format_short, 'Y');
507 if( $pos_y == 0 ){
508 $date_format_short = substr_replace( $date_format_short, '', $pos_y, 2 );
509 }
510 else {
511 $date_format_short = substr_replace( $date_format_short, '', $pos_y - 1, 2 );
512 }
513 }
514
515 if( isset($skip['month']) ){
516 $tags = array('m', 'n', 'M');
517 foreach( $tags as $t ){
518 $pos_m = strpos($date_format_short, $t);
519 if( $pos_m !== FALSE )
520 break;
521 }
522
523 // month going first, do not replace
524 if( $pos_m_original == 0 ){
525 // $date_format_short = substr_replace( $date_format_short, '', $pos_m, 2 );
526 }
527 else {
528 // month going first, do not replace
529 if( $pos_m == 0 ){
530 $date_format_short = substr_replace( $date_format_short, '', $pos_m, 2 );
531 }
532 else {
533 $date_format_short = substr_replace( $date_format_short, '', $pos_m - 1, 2 );
534 }
535 }
536 }
537
538 if( $pos_y == 0 ){ // skip year in the second part
539 $date_format1 = $date_format;
540 $date_format2 = $date_format_short;
541 }
542 else {
543 $date_format1 = $date_format_short;
544 $date_format2 = $date_format;
545 }
546
547 $this->setDateDb( $date1 );
548
549 $view_date1 = $this->formatDate( $date_format1 );
550 if( $with_weekday ){
551 $view_date1 = $this->formatWeekdayShort() . ', ' . $view_date1;
552 }
553 $return[] = $view_date1;
554
555 $this->setDateDb( $date2 );
556 $view_date2 = $this->formatDate( $date_format2 );
557 if( $with_weekday ){
558 $view_date2 = $this->formatWeekdayShort() . ', ' . $view_date2;
559 }
560 $return[] = $view_date2;
561 }
562 else {
563 $this->setDateDb( $date1 );
564 $view_date1 = $this->formatDate();
565 if( $with_weekday ){
566 $view_date1 = $this->formatWeekdayShort() . ', ' . $view_date1;
567 }
568 $return[] = $view_date1;
569
570 $this->setDateDb( $date2 );
571 $view_date2 = $this->formatDate();
572 if( $with_weekday ){
573 $view_date2 = $this->formatWeekdayShort() . ', ' . $view_date2;
574 }
575 $return[] = $view_date2;
576 }
577
578 return $return;
579 }
580
581 public function getMonthMatrix( $skipWeekdays = array(), $daysPerWeek = 7 )
582 {
583 $overlap = TRUE; // if to show dates of prev/next month
584 $overlap = FALSE; // if to show dates of prev/next month
585
586 $matrix = array();
587 $currentMonthDay = 0;
588
589 $this->setStartMonth();
590 if( $overlap ){
591 $this->setStartWeek();
592 }
593 $startDate = $this->formatDateDb();
594
595 // echo "END DATE = $endDate<br>";
596
597 $this->setEndMonth();
598 if( $overlap ){
599 // $this->setEndWeek();
600 }
601 $endDate = $this->formatDateDb();
602 // echo "START/END DATE = $startDate/$endDate<br>";
603
604 $rexDate = $startDate;
605 if( $overlap ){
606 $this->setDateDb( $startDate );
607 $this->setStartWeek();
608 $rexDate = $this->formatDateDb();
609 }
610
611 $this->setDateDb( $startDate );
612 $this->setStartWeek();
613 $rexDate = $this->formatDateDb();
614
615 // echo "START DATE = $startDate, END DATE = $endDate, REX DATE = $rexDate<br>";
616
617 $this->setDateDb( $rexDate );
618 while( $rexDate <= $endDate ){
619 $week = array();
620 $weekSet = FALSE;
621 for( $weekDay = 0; $weekDay < $daysPerWeek; $weekDay++ ){
622 $thisWeekday = $this->getWeekday();
623 $setDate = $rexDate;
624
625 if( ! $overlap ){
626 if(
627 ( $rexDate > $endDate ) OR
628 ( $rexDate < $startDate )
629 ){
630 $setDate = NULL;
631 }
632 }
633
634 // $week[ $thisWeekday ] = $setDate;
635
636 if( (! $skipWeekdays) OR (! in_array($thisWeekday, $skipWeekdays)) ){
637 $week[] = $setDate;
638 if( NULL !== $setDate ){
639 $weekSet = TRUE;
640 }
641 }
642
643 $this->modify('+1 day');
644 $rexDate = $this->formatDateDb();
645
646 // if( $exact && ($rexDate >= $endDate) ){
647 // break;
648 // }
649 }
650
651 if( $weekSet )
652 $matrix[] = $week;
653 }
654 return $matrix;
655 }
656
657 public function getWeeksMatrix( $weeks = 4, $skipWeekdays = array() )
658 {
659 $matrix = array();
660 $currentMonthDay = 0;
661
662 $this->setStartWeek();
663 $startDate = $this->formatDateDb();
664
665 // echo "END DATE = $endDate<br>";
666 $this->modify( '+' . $weeks . ' weeks' )->modify('-1 day');
667 $endDate = $this->formatDateDb();
668 // echo "START/END DATE = $startDate/$endDate<br>";
669
670 $rexDate = $startDate;
671
672 // echo "START DATE = $startDate, END DATE = $endDate, REX DATE = $rexDate<br>";
673
674 $this->setDateDb( $rexDate );
675 while( $rexDate <= $endDate ){
676 $week = array();
677 $weekSet = FALSE;
678 for( $weekDay = 0; $weekDay <= 6; $weekDay++ ){
679 $thisWeekday = $this->getWeekday();
680 $setDate = $rexDate;
681
682 // $week[ $thisWeekday ] = $setDate;
683
684 if( (! $skipWeekdays) OR (! in_array($thisWeekday, $skipWeekdays)) ){
685 $week[] = $setDate;
686 if( NULL !== $setDate ){
687 $weekSet = TRUE;
688 }
689 }
690
691 $this->modify('+1 day');
692 $rexDate = $this->formatDateDb();
693
694 // if( $exact && ($rexDate >= $endDate) ){
695 // break;
696 // }
697 }
698
699 if( $weekSet )
700 $matrix[] = $week;
701 }
702 return $matrix;
703 }
704
705 public function getParts()
706 {
707 $full = $this->formatDateTimeDb();
708
709 $year = substr( $full, 0, 4 );
710 $month = substr( $full, 4, 2 );
711 $day = substr( $full, 6, 2 );
712 $hour = substr( $full, 8, 2 );
713 $min = substr( $full, 10, 2 );
714
715 $return = array( $year, $month, $day, $hour, $min );
716 return $return;
717 }
718
719 public function getWeekdays()
720 {
721 $return = array();
722
723 $wkds = array( 0, 1, 2, 3, 4, 5, 6 );
724 $wkds = $this->sortWeekdays( $wkds );
725
726 reset( $wkds );
727 foreach( $wkds as $wkd ){
728 $return[ $wkd ] = '__' . $this->_weekdays[$wkd] . '__';
729 }
730 return $return;
731 }
732
733 public function sortWeekdays( $wds )
734 {
735 $return = array();
736 $later = array();
737
738 sort( $wds );
739 reset( $wds );
740 foreach( $wds as $wd ){
741 if( $wd < $this->weekStartsOn )
742 $later[] = $wd;
743 else
744 $return[] = $wd;
745 }
746 $return = array_merge( $return, $later );
747 return $return;
748 }
749
750 public function formatDuration( $seconds )
751 {
752 $hours = floor( $seconds / (60 * 60) );
753 $remain = $seconds - $hours * (60 * 60);
754 $minutes = floor( $remain / 60 );
755
756 $hoursView = $hours;
757 $minutesView = sprintf( '%02d', $minutes );
758
759 $return = $hoursView . ':' . $minutesView;
760 // $return = gmdate( "H:i", $this->getDuration() );
761 return $return;
762 }
763
764 public function getTimezones()
765 {
766 $skipStarts = array('Brazil/', 'Canada/', 'Chile/', 'Etc/', 'Mexico/', 'US/');
767 $skipStarts = array( 'Etc/' );
768 // $skipStarts = array();
769 $return = array();
770
771 if( defined('DateTimeZone::ALL_WITH_BC') )
772 $timezones = timezone_identifiers_list( DateTimeZone::ALL_WITH_BC );
773 else
774 $timezones = timezone_identifiers_list();
775
776 reset( $timezones );
777 foreach( $timezones as $tz ){
778 if( false === strpos($tz, "/") )
779 continue;
780
781 $skipIt = false;
782 reset( $skipStarts );
783 foreach( $skipStarts as $skip ){
784 if( substr($tz, 0, strlen($skip)) == $skip ){
785 $skipIt = true;
786 break;
787 }
788 }
789 if( $skipIt )
790 continue;
791
792 $tzTitle = $this->timezoneTitle( $tz );
793 $return[ $tz ] = $tzTitle;
794 }
795
796 return $return;
797 }
798
799 public function timezoneTitle( $tz, $showOffset = FALSE )
800 {
801 if( is_array($tz) )
802 $tz = $tz[0];
803
804 $tzobj = new DateTimeZone( $tz );
805 $dtobj = new DateTime();
806 $dtobj->setTimezone( $tzobj );
807
808 if( $showOffset ){
809 $offset = $tzobj->getOffset( $dtobj );
810 $offsetString = 'GMT';
811 $offsetString .= ($offset >= 0) ? '+' : '';
812 $offsetString = $offsetString . ( $offset/(60 * 60) );
813 $return = $tz . ' (' . $offsetString . ')';
814 }
815 else {
816 $return = $tz;
817 }
818
819 return $return;
820 }
821
822 public function getDefaultTimezone()
823 {
824 $return = date_default_timezone_get();
825
826 if( defined('WPINC') ){
827 $tz = get_option('timezone_string');
828 if( ! strlen($tz) ){
829 $offset = get_option('gmt_offset');
830 if( $offset ){
831 $tz = 'Etc/GMT';
832 if( $offset > 0 ){
833 $tz .= '+' . $offset;
834 }
835 else {
836 $tz .= '-' . -$offset;
837 }
838 }
839 }
840
841 if( strlen($tz) ){
842 $return = $tz;
843 }
844 }
845
846 return $return;
847 }
848 }