diff --git a/htdocs/admin/agenda_extsites.php b/htdocs/admin/agenda_extsites.php index 633b62f2316..2e113f22430 100644 --- a/htdocs/admin/agenda_extsites.php +++ b/htdocs/admin/agenda_extsites.php @@ -65,6 +65,7 @@ if ($actionsave) { $name=trim(GETPOST('AGENDA_EXT_NAME'.$i,'alpha')); $src=trim(GETPOST('AGENDA_EXT_SRC'.$i,'alpha')); + $offsettz=trim(GETPOST('AGENDA_EXT_OFFSETTZ'.$i,'alpha')); $color=trim(GETPOST('AGENDA_EXT_COLOR'.$i,'alpha')); if ($color=='-1') $color=''; $enabled=trim(GETPOST('AGENDA_EXT_ENABLED'.$i,'alpha')); @@ -82,6 +83,8 @@ if ($actionsave) if (! $res > 0) $error++; $res=dolibarr_set_const($db,'AGENDA_EXT_SRC'.$i,$src,'chaine',0,'',$conf->entity); if (! $res > 0) $error++; + $res=dolibarr_set_const($db,'AGENDA_EXT_OFFSETTZ'.$i,$offsettz,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; $res=dolibarr_set_const($db,'AGENDA_EXT_COLOR'.$i,$color,'chaine',0,'',$conf->entity); if (! $res > 0) $error++; $res=dolibarr_set_const($db,'AGENDA_EXT_ENABLED'.$i,$enabled,'chaine',0,'',$conf->entity); @@ -191,6 +194,7 @@ print ""; print "".$langs->trans("Parameter").""; print "".$langs->trans("Name").""; print "".$langs->trans("ExtSiteUrlAgenda")." (".$langs->trans("Example").': http://yoursite/agenda/agenda.ics)'; +print "".$form->textwithpicto($langs->trans("FixTZ"), $langs->trans("FillFixTZOnlyIfRequired"), 1).''; print ''.$langs->trans("Color").''; print ""; @@ -201,6 +205,7 @@ while ($i <= $MAXAGENDA) $key=$i; $name='AGENDA_EXT_NAME'.$key; $src='AGENDA_EXT_SRC'.$key; + $offsettz='AGENDA_EXT_OFFSETTZ'.$key; $color='AGENDA_EXT_COLOR'.$key; $enabled='AGENDA_EXT_ENABLED'.$key; @@ -212,6 +217,8 @@ while ($i <= $MAXAGENDA) print ''; // URL print ''; + // Offset TZ + print ''; // Color (Possible colors are limited by Google) print ''; //print $formadmin->selectColor($conf->global->$color, "google_agenda_color".$key, $colorlist); diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index c414d3409d6..f445c7f3596 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -179,12 +179,13 @@ if (empty($conf->global->AGENDA_DISABLE_EXT)) $i++; $source='AGENDA_EXT_SRC'.$i; $name='AGENDA_EXT_NAME'.$i; + $offsettz='AGENDA_EXT_OFFSETTZ'.$i; $color='AGENDA_EXT_COLOR'.$i; $buggedfile='AGENDA_EXT_BUGGEDFILE'.$i; if (! empty($conf->global->$source) && ! empty($conf->global->$name)) { // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight' - $listofextcals[]=array('src'=>$conf->global->$source,'name'=>$conf->global->$name,'color'=>$conf->global->$color,'buggedfile'=>(isset($conf->global->buggedfile)?$conf->global->buggedfile:0)); + $listofextcals[]=array('src'=>$conf->global->$source,'name'=>$conf->global->$name,'offsettz'=>$conf->global->$offsettz,'color'=>$conf->global->$color,'buggedfile'=>(isset($conf->global->buggedfile)?$conf->global->buggedfile:0)); } } } @@ -197,13 +198,14 @@ if (empty($user->conf->AGENDA_DISABLE_EXT)) $i++; $source='AGENDA_EXT_SRC_'.$user->id.'_'.$i; $name='AGENDA_EXT_NAME_'.$user->id.'_'.$i; + $offsettz='AGENDA_EXT_OFFSETTZ_'.$user->id.'_'.$i; $color='AGENDA_EXT_COLOR_'.$user->id.'_'.$i; $enabled='AGENDA_EXT_ENABLED_'.$user->id.'_'.$i; $buggedfile='AGENDA_EXT_BUGGEDFILE_'.$user->id.'_'.$i; if (! empty($user->conf->$source) && ! empty($user->conf->$name)) { // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight' - $listofextcals[]=array('src'=>$user->conf->$source,'name'=>$user->conf->$name,'color'=>$user->conf->$color,'buggedfile'=>(isset($user->conf->buggedfile)?$user->conf->buggedfile:0)); + $listofextcals[]=array('src'=>$user->conf->$source,'name'=>$user->conf->$name,'offsettz'=>$user->conf->$offsettz,'color'=>$user->conf->$color,'buggedfile'=>(isset($user->conf->buggedfile)?$user->conf->buggedfile:0)); } } } @@ -507,8 +509,12 @@ if ($resql) // Create a new object action $event=new ActionComm($db); $event->id=$obj->id; - $event->datep=$db->jdate($obj->datep); // datep and datef are GMT date + + $event->datep=$db->jdate($obj->datep); // datep and datef are GMT date. Example: 1970-01-01 01:00:00, jdate will return 0 if TZ of PHP server is Europe/Berlin $event->datef=$db->jdate($obj->datep2); + //var_dump($obj->datep); + //var_dump($event->datep); + $event->type_code=$obj->type_code; $event->type_label=$obj->type_label; $event->libelle=$obj->label; @@ -664,6 +670,7 @@ if (count($listofextcals)) { $url=$extcal['src']; // Example: https://www.google.com/calendar/ical/eldy10%40gmail.com/private-cde92aa7d7e0ef6110010a821a2aaeb/basic.ics $namecal = $extcal['name']; + $offsettz = $extcal['offsettz']; $colorcal = $extcal['color']; $buggedfile = $extcal['buggedfile']; //print "url=".$url." namecal=".$namecal." colorcal=".$colorcal." buggedfile=".$buggedfile; @@ -805,12 +812,22 @@ if (count($listofextcals)) { $datestart=$icalevent['DTSTART']; $dateend=$icalevent['DTEND']; + + $datestart+=+($offsettz * 3600); + $dateend+=+($offsettz * 3600); + $addevent=true; + //var_dump($offsettz); + //var_dump(dol_print_date($datestart, 'dayhour', 'gmt')); } elseif (isset($icalevent['DTSTART']['unixtime'])) // File contains a local timezone + a TZ (for example when using bluemind) { $datestart=$icalevent['DTSTART']['unixtime']; $dateend=$icalevent['DTEND']['unixtime']; + + $datestart+=+($offsettz * 3600); + $dateend+=+($offsettz * 3600); + // $buggedfile is set to uselocalandtznodaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtznodaylight' if ($buggedfile === 'uselocalandtznodaylight') // unixtime is a local date that does not take daylight into account, TZID is +1 for example for 'Europe/Paris' in summer instead of 2 { @@ -1308,7 +1325,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa // Hour start if ($tmpyearstart == $annee && $tmpmonthstart == $mois && $tmpdaystart == $jour) { - $daterange.=dol_print_date($event->date_start_in_calendar,'%H:%M'); + $daterange.=dol_print_date($event->date_start_in_calendar,'%H:%M'); // Il faudrait utiliser ici tzuser, mais si on ne peut pas car qd on rentre un date dans fiche action, en input la conversion local->gmt se base sur le TZ server et non user if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) { if ($tmpyearstart == $tmpyearend && $tmpmonthstart == $tmpmonthend && $tmpdaystart == $tmpdayend) @@ -1328,7 +1345,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) { if ($tmpyearend == $annee && $tmpmonthend == $mois && $tmpdayend == $jour) - $daterange.=dol_print_date($event->date_end_in_calendar,'%H:%M'); + $daterange.=dol_print_date($event->date_end_in_calendar,'%H:%M'); // Il faudrait utiliser ici tzuser, mais si on ne peut pas car qd on rentre un date dans fiche action, en input la conversion local->gmt se base sur le TZ server et non user } //print $daterange; if ($event->type_code != 'ICALEVENT') diff --git a/htdocs/core/lib/date.lib.php b/htdocs/core/lib/date.lib.php index 9eae0038194..67c7df4be5b 100644 --- a/htdocs/core/lib/date.lib.php +++ b/htdocs/core/lib/date.lib.php @@ -88,6 +88,7 @@ function getServerTimeZoneInt($refgmtdate='now') if ($refgmtdate == 'now') $newrefgmtdate=$yearref.'-'.$monthref.'-'.$dayref; elseif ($refgmtdate == 'summer') $newrefgmtdate=$yearref.'-08-01'; else $newrefgmtdate=$yearref.'-01-01'; + $newrefgmtdate.='T00:00:00+00:00'; $localtz = new DateTimeZone(getServerTimeZoneString()); $localdt = new DateTime($newrefgmtdate, $localtz); $tmp=-1*$localtz->getOffset($localdt); @@ -97,30 +98,6 @@ function getServerTimeZoneInt($refgmtdate='now') { $tmp=0; dol_print_error('','PHP version must be 5.3+'); - /* - // Method 2 (does not include daylight, not supported by adodb) - if ($refgmtdate == 'now') - { - if (ini_get("date.timezone")=='UTC') return 0; - // We don't know server timezone string, so we don't know location, so we can't guess daylight. We assume we use same than client but this may be a bug. - $gmtnow=dol_now('gmt'); $yearref=dol_print_date($gmtnow,'%Y'); $monthref=dol_print_date($gmtnow,'%m'); $dayref=dol_print_date($gmtnow,'%d'); - if (dol_stringtotime($_SESSION['dol_dst_first']) <= $gmtnow && $gmtnow < dol_stringtotime($_SESSION['dol_dst_second'])) $daylight=1; - else $daylight=0; - $tmp=dol_mktime(0,0,0,$monthref,$dayref,$yearref,false,0)-dol_mktime(0,0,0,$monthref,$dayref,$yearref,true,0)-($daylight*3600); - return 'unknown'; // For true result - } - elseif ($refgmtdate == 'summer') - { - if (ini_get("date.timezone")=='UTC') return 0; - // We don't know server timezone string, so we don't know location, so we can't guess daylight. We assume we use same than client but this may be a bug. - $gmtnow=dol_now('gmt'); $yearref=dol_print_date($gmtnow,'%Y'); $monthref='08'; $dayref='01'; - if (dol_stringtotime($_SESSION['dol_dst_first']) <= dol_stringtotime($yearref.'-'.$monthref.'-'.$dayref) && dol_stringtotime($yearref.'-'.$monthref.'-'.$dayref) < dol_stringtotime($_SESSION['dol_dst_second'])) $daylight=1; - else $daylight=0; - $tmp=dol_mktime(0,0,0,$monthref,$dayref,$yearref,false,0)-dol_mktime(0,0,0,$monthref,$dayref,$yearref,true,0)-($daylight*3600); - return 'unknown'; // For true result - } - else $tmp=dol_mktime(0,0,0,1,1,1970); - */ } $tz=round(($tmp<0?1:-1)*abs($tmp/3600)); return $tz; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 30d8e7a5045..6074f6fe841 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -962,7 +962,8 @@ function dol_strftime($fmt, $ts=false, $is_gmt=false) * "day", "daytext", "dayhour", "dayhourldap", "dayhourtext", "dayrfc", "dayhourrfc" * @param string $tzoutput true or 'gmt' => string is for Greenwich location * false or 'tzserver' => output string is for local PHP server TZ usage - * 'tzuser' => output string is for local browser TZ usage + * 'tzuser' => output string is for user TZ (current browser TZ with current dst) + * 'tzuserrel' => output string is for user TZ (current browser TZ with dst or not, depending on date position) * @param Translate $outputlangs Object lang that contains language for text translation. * @param boolean $encodetooutput false=no convert into output pagecode * @return string Formated date or '' if time is null @@ -984,19 +985,17 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e if ($tzoutput == 'tzserver') { $to_gmt=false; - $offsettz=$offsetdst=0; + $offsettzstring=@date_default_timezone_get(); // Example 'Europe/Berlin' or 'Indian/Reunion' + $offsettz=0; + $offsetdst=0; } elseif ($tzoutput == 'tzuser') { $to_gmt=true; + $offsettzstring=(empty($_SESSION['dol_tz_string'])?'UTC':$_SESSION['dol_tz_string']); // Example 'Europe/Berlin' or 'Indian/Reunion' $offsettz=(empty($_SESSION['dol_tz'])?0:$_SESSION['dol_tz'])*60*60; $offsetdst=(empty($_SESSION['dol_dst'])?0:$_SESSION['dol_dst'])*60*60; } - elseif ($tzoutput == 'tzcompany') - { - $to_gmt=false; - $offsettz=$offsetdst=0; // TODO Define this and use it later - } } } if (! is_object($outputlangs)) $outputlangs=$langs; @@ -1045,9 +1044,9 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e $format=str_replace('%A','__A__',$format); } - // Analyze date (deprecated) Ex: 1970-01-01, 1970-01-01 01:00:00, 19700101010000 + // Analyze date if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+) ?([0-9]+)?:?([0-9]+)?:?([0-9]+)?/i',$time,$reg) - || preg_match('/^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])$/i',$time,$reg)) + || preg_match('/^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])$/i',$time,$reg)) // Deprecated. Ex: 1970-01-01, 1970-01-01 01:00:00, 19700101010000 { // This part of code should not be used. TODO Remove this. dol_syslog("Functions.lib::dol_print_date function call with deprecated value of time in page ".$_SERVER["PHP_SELF"], LOG_WARNING); @@ -1067,7 +1066,7 @@ function dol_print_date($time,$format='',$tzoutput='tzserver',$outputlangs='',$e // Date is a timestamps if ($time < 100000000000) // Protection against bad date values { - $ret=adodb_strftime($format,$time+$offsettz+$offsetdst,$to_gmt); // TODO Remove this + $ret=adodb_strftime($format,$time+$offsettz+$offsetdst,$to_gmt); // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring. } else $ret='Bad value '.$time.' for date'; } @@ -1198,13 +1197,13 @@ function dol_mktime($hour,$minute,$second,$month,$day,$year,$gm=false,$check=1) { if (empty($gm) || $gm === 'server') { - $default_timezone=@date_default_timezone_get(); + $default_timezone=@date_default_timezone_get(); // Example 'Europe/Berlin' $localtz = new DateTimeZone($default_timezone); } else if ($gm === 'user') { - // We use dol_tz_string first because it contains dst. - $default_timezone=(empty($_SESSION["dol_tz_string"])?@date_default_timezone_get():$_SESSION["dol_tz_string"]); + // We use dol_tz_string first because it is more reliable. + $default_timezone=(empty($_SESSION["dol_tz_string"])?@date_default_timezone_get():$_SESSION["dol_tz_string"]); // Example 'Europe/Berlin' try { $localtz = new DateTimeZone($default_timezone); } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 59b495d8a12..e8d227d3921 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1663,6 +1663,8 @@ OpportunityPercent=When you create an opportunity, you will defined an estimated TemplateForElement=This template record is dedicated to which element TypeOfTemplate=Type of template TemplateIsVisibleByOwnerOnly=Template is visible by owner only +FixTZ=TimeZone fix +FillFixTZOnlyIfRequired=Example: +2 (fill only if problem experienced) MailToSendProposal=To send customer proposal MailToSendOrder=To send customer order MailToSendInvoice=To send customer invoice diff --git a/htdocs/user/agenda_extsites.php b/htdocs/user/agenda_extsites.php index 6699e30023b..cd38d7a2965 100644 --- a/htdocs/user/agenda_extsites.php +++ b/htdocs/user/agenda_extsites.php @@ -84,6 +84,7 @@ if ($actionsave) { $name=trim(GETPOST('AGENDA_EXT_NAME_'.$id.'_'.$i,'alpha')); $src=trim(GETPOST('AGENDA_EXT_SRC_'.$id.'_'.$i,'alpha')); + $offsettz=trim(GETPOST('AGENDA_EXT_OFFSETTZ_'.$id.'_'.$i,'alpha')); $color=trim(GETPOST('AGENDA_EXT_COLOR_'.$id.'_'.$i,'alpha')); if ($color=='-1') $color=''; $enabled=trim(GETPOST('AGENDA_EXT_ENABLED_'.$id.'_'.$i,'alpha')); @@ -98,6 +99,7 @@ if ($actionsave) $tabparam['AGENDA_EXT_NAME_'.$id.'_'.$i]=$name; $tabparam['AGENDA_EXT_SRC_'.$id.'_'.$i]=$src; + $tabparam['AGENDA_EXT_OFFSETTZ_'.$id.'_'.$i]=$offsettz; $tabparam['AGENDA_EXT_COLOR_'.$id.'_'.$i]=$color; $tabparam['AGENDA_EXT_ENABLED_'.$id.'_'.$i]=$enabled; @@ -156,6 +158,7 @@ print ""; print "".$langs->trans("Parameter").""; print "".$langs->trans("Name").""; print "".$langs->trans("ExtSiteUrlAgenda")." (".$langs->trans("Example").': http://yoursite/agenda/agenda.ics)'; +print "".$form->textwithpicto($langs->trans("FixTZ"), $langs->trans("FillFixTZOnlyIfRequired"), 1).''; print ''.$langs->trans("Color").''; print ""; @@ -166,6 +169,7 @@ while ($i <= $MAXAGENDA) $key=$i; $name='AGENDA_EXT_NAME_'.$id.'_'.$key; $src='AGENDA_EXT_SRC_'.$id.'_'.$key; + $offsettz='AGENDA_EXT_OFFSETTZ_'.$id.'_'.$key; $color='AGENDA_EXT_COLOR_'.$id.'_'.$key; $var=!$var; @@ -176,6 +180,8 @@ while ($i <= $MAXAGENDA) print ''; // URL print ''; + // Offset TZ + print ''; // Color (Possible colors are limited by Google) print ''; //print $formadmin->selectColor($conf->global->$color, "google_agenda_color".$key, $colorlist);