2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-22 20:24:36 +00:00

HOMESTATEtk: improved daytime calculation at switch point

git-svn-id: https://svn.fhem.de/fhem/trunk@14339 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
jpawlowski 2017-05-21 15:31:50 +00:00
parent 831d260f0e
commit 87e7da0a05
2 changed files with 81 additions and 66 deletions

View File

@ -139,6 +139,7 @@ sub HOMESTATEtk_InitializeDev($) {
my $langUc = uc($lang); my $langUc = uc($lang);
my @error; my @error;
delete $hash->{NEXT_EVENT};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
no strict "refs"; no strict "refs";
@ -254,6 +255,7 @@ sub HOMESTATEtk_Define($$$) {
$hash->{MOD_INIT} = 1; $hash->{MOD_INIT} = 1;
$hash->{NOTIFYDEV} = "global"; $hash->{NOTIFYDEV} = "global";
delete $hash->{NEXT_EVENT};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
# set default settings on first define # set default settings on first define
@ -267,12 +269,12 @@ sub HOMESTATEtk_Define($$$) {
$attr{$name}{icon} = "control_building_control" $attr{$name}{icon} = "control_building_control"
if ( $TYPE eq "HOMESTATE" ); if ( $TYPE eq "HOMESTATE" );
$attr{$name}{icon} = "control_building_eg" $attr{$name}{icon} = "control_building_eg"
if ( $TYPE eq "FLOORSTATE" ); if ( $TYPE eq "SECTIONSTATE" );
$attr{$name}{icon} = "floor" $attr{$name}{icon} = "floor"
if ( $TYPE eq "ROOMSTATE" ); if ( $TYPE eq "ROOMSTATE" );
# find HOMESTATE device # find HOMESTATE device
if ( $TYPE eq "ROOMSTATE" || $TYPE eq "FLOORSTATE" ) { if ( $TYPE eq "ROOMSTATE" || $TYPE eq "SECTIONSTATE" ) {
my @homestates = devspec2array("TYPE=HOMESTATE"); my @homestates = devspec2array("TYPE=HOMESTATE");
if ( scalar @homestates ) { if ( scalar @homestates ) {
$attr{$name}{"HomestateDevices"} = $homestates[0]; $attr{$name}{"HomestateDevices"} = $homestates[0];
@ -308,7 +310,7 @@ sub HOMESTATEtk_Define($$$) {
} }
# find ROOMSTATE device # find ROOMSTATE device
if ( $TYPE eq "FLOORSTATE" ) { if ( $TYPE eq "SECTIONSTATE" ) {
my @roomstates = devspec2array("TYPE=ROOMSTATE"); my @roomstates = devspec2array("TYPE=ROOMSTATE");
unless ( scalar @roomstates ) { unless ( scalar @roomstates ) {
my $n = "Room"; my $n = "Room";
@ -359,12 +361,6 @@ sub HOMESTATEtk_Define($$$) {
"Auto-created by $TYPE module for use with HOMESTATE Toolkit"; "Auto-created by $TYPE module for use with HOMESTATE Toolkit";
$attr{$name}{"ResidentsDevices"} = $n; $attr{$name}{"ResidentsDevices"} = $n;
$attr{$n}{room} = $attr{$name}{room}; $attr{$n}{room} = $attr{$name}{room};
$attr{$name}{"Lang"} = $attr{ $residents[0] }{rgr_lang}
if ( $attr{ $residents[0] }
&& $attr{ $residents[0] }{rgr_lang} );
$attr{$name}{"Lang"} = $attr{ $residents[0] }{rr_lang}
if ( $attr{ $residents[0] }
&& $attr{ $residents[0] }{rr_lang} );
HOMESTATEtk_Attr( "set", $name, "Lang", $attr{$name}{"Lang"} ) HOMESTATEtk_Attr( "set", $name, "Lang", $attr{$name}{"Lang"} )
if $attr{$name}{"Lang"}; if $attr{$name}{"Lang"};
@ -379,6 +375,7 @@ sub HOMESTATEtk_Define($$$) {
sub HOMESTATEtk_Undefine($$) { sub HOMESTATEtk_Undefine($$) {
my ( $hash, $name ) = @_; my ( $hash, $name ) = @_;
delete $hash->{NEXT_EVENT};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
return undef; return undef;
} }
@ -631,11 +628,13 @@ sub HOMESTATEtk_Get($$$) {
return "invalid date format $date" return "invalid date format $date"
unless ( !$date unless ( !$date
|| $date =~ m/^\d{4}\-\d{2}-\d{2}$/ || $date =~ m/^\d{4}\-\d{2}-\d{2}$/
|| $date =~ m/^\d{2}-\d{2}$/ ); || $date =~ m/^\d{2}-\d{2}$/
|| $date =~ m/^\d{10}$/ );
return "invalid time format $time" return "invalid time format $time"
unless ( !$time unless ( !$time
|| $time =~ m/^\d{2}:\d{2}(:\d{2})?$/ ); || $time =~ m/^\d{2}:\d{2}(:\d{2})?$/ );
unless ( $date =~ m/^\d{10}$/ ) {
my ( $sec, $min, $hour, $mday, $mon, $year ) = UConv::_time(); my ( $sec, $min, $hour, $mday, $mon, $year ) = UConv::_time();
$date = "$year-$date" if ( $date =~ m/^\d{2}-\d{2}$/ ); $date = "$year-$date" if ( $date =~ m/^\d{2}-\d{2}$/ );
$time .= ":00" if ( $time && $time =~ m/^\d{2}:\d{2}$/ ); $time .= ":00" if ( $time && $time =~ m/^\d{2}:\d{2}$/ );
@ -647,6 +646,7 @@ sub HOMESTATEtk_Get($$$) {
# $date = timelocal( $sec, $min, $hour, $mday, $mon - 1, $year ); # $date = timelocal( $sec, $min, $hour, $mday, $mon - 1, $year );
$date = time_str2num($date); $date = time_str2num($date);
} }
}
#TODO timelocal? 03-26 results in wrong timestamp #TODO timelocal? 03-26 results in wrong timestamp
# return PrintHash( # return PrintHash(
@ -679,7 +679,7 @@ sub HOMESTATEtk_Attr(@) {
my $security = ReadingsVal( $name, "security", "" ); my $security = ReadingsVal( $name, "security", "" );
return return
"Device is currently $security and attributes cannot be changed at this state" "Device is currently $security and attributes cannot be changed at this state"
unless ( !$init_done || $security =~ m/^unlocked|locked$/ ); unless ( !$init_done || $security =~ m/^unlocked|locked$/ );
if ( $attribute eq "HomestateDevices" ) { if ( $attribute eq "HomestateDevices" ) {
@ -696,8 +696,8 @@ sub HOMESTATEtk_Attr(@) {
unless ( $cmd eq "del" unless ( $cmd eq "del"
|| $value =~ m/^[A-Za-z\d._]+(?:,[A-Za-z\d._]*)*$/ ); || $value =~ m/^[A-Za-z\d._]+(?:,[A-Za-z\d._]*)*$/ );
delete $hash->{FLOORSTATES}; delete $hash->{SECTIONSTATES};
$hash->{FLOORSTATES} = $value unless ( $cmd eq "del" ); $hash->{SECTIONSTATES} = $value unless ( $cmd eq "del" );
} }
elsif ( $attribute eq "RoomstateDevices" ) { elsif ( $attribute eq "RoomstateDevices" ) {
@ -775,10 +775,10 @@ sub HOMESTATEtk_Attr(@) {
if ( !defined( $attr{$name}{group} ) if ( !defined( $attr{$name}{group} )
|| $attr{$name}{group} eq "Home State" ); || $attr{$name}{group} eq "Home State" );
} }
if ( $TYPE eq "FLOORSTATE" ) { if ( $TYPE eq "SECTIONSTATE" ) {
$attr{$name}{group} = "Flurstatus" $attr{$name}{group} = "Bereichstatus"
if ( !defined( $attr{$name}{group} ) if ( !defined( $attr{$name}{group} )
|| $attr{$name}{group} eq "Floor State" ); || $attr{$name}{group} eq "Section State" );
} }
if ( $TYPE eq "ROOMSTATE" ) { if ( $TYPE eq "ROOMSTATE" ) {
$attr{$name}{group} = "Raumstatus" $attr{$name}{group} = "Raumstatus"
@ -800,10 +800,10 @@ sub HOMESTATEtk_Attr(@) {
if ( !defined( $attr{$name}{group} ) if ( !defined( $attr{$name}{group} )
|| $attr{$name}{group} eq "Zuhause Status" ); || $attr{$name}{group} eq "Zuhause Status" );
} }
if ( $TYPE eq "FLOORSTATE" ) { if ( $TYPE eq "SECTIONSTATE" ) {
$attr{$name}{group} = "Floor State" $attr{$name}{group} = "Section State"
if ( !defined( $attr{$name}{group} ) if ( !defined( $attr{$name}{group} )
|| $attr{$name}{group} eq "Flurstatus" ); || $attr{$name}{group} eq "Bereichstatus" );
} }
if ( $TYPE eq "ROOMSTATE" ) { if ( $TYPE eq "ROOMSTATE" ) {
$attr{$name}{group} = "Room State" $attr{$name}{group} = "Room State"
@ -891,10 +891,12 @@ m/^((?:DELETE)?ATTR)\s+([A-Za-z\d._]+)\s+([A-Za-z\d_\.\-\/]+)(?:\s+(.*)\s*)?$/
# when own attributes were changed # when own attributes were changed
if ( $d eq $name ) { if ( $d eq $name ) {
if ( defined( &{'DoInitDev'} ) ) { if ( defined( &{'DoInitDev'} ) ) {
delete $hash->{NEXT_EVENT};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer( gettimeofday() + 0.5, "DoInitDev", $hash ); InternalTimer( gettimeofday() + 0.5, "DoInitDev", $hash );
} }
else { else {
delete $hash->{NEXT_EVENT};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
InternalTimer( gettimeofday() + 0.5, InternalTimer( gettimeofday() + 0.5,
"RESIDENTStk_DoInitDev", $hash ); "RESIDENTStk_DoInitDev", $hash );
@ -912,7 +914,7 @@ m/^((?:DELETE)?ATTR)\s+([A-Za-z\d._]+)\s+([A-Za-z\d_\.\-\/]+)(?:\s+(.*)\s*)?$/
# only when they hit HOMESTATE devices # only when they hit HOMESTATE devices
if ( $TYPE ne $devType if ( $TYPE ne $devType
&& $devType =~ && $devType =~
m/^HOMESTATE|FLOORSTATE|ROOMSTATE|RESIDENTS|ROOMMATE|GUEST$/ ) m/^HOMESTATE|SECTIONSTATE|ROOMSTATE|RESIDENTS|ROOMMATE|GUEST$/ )
{ {
my $events = deviceEvents( $dev, 1 ); my $events = deviceEvents( $dev, 1 );
@ -971,31 +973,31 @@ sub HOMESTATEtk_findHomestateSlaves($;$) {
if ( $hash->{TYPE} eq "HOMESTATE" ) { if ( $hash->{TYPE} eq "HOMESTATE" ) {
my @FLOORSTATES; my @SECTIONSTATES;
foreach ( devspec2array("TYPE=FLOORSTATE") ) { foreach ( devspec2array("TYPE=SECTIONSTATE") ) {
next next
unless ( unless (
defined( $defs{$_}{FLOORSTATES} ) defined( $defs{$_}{SECTIONSTATES} )
&& grep { $hash->{NAME} eq $_ } && grep { $hash->{NAME} eq $_ }
split( /,/, $defs{$_}{FLOORSTATES} ) split( /,/, $defs{$_}{SECTIONSTATES} )
); );
push @FLOORSTATES, $_; push @SECTIONSTATES, $_;
} }
if ( scalar @FLOORSTATES ) { if ( scalar @SECTIONSTATES ) {
$hash->{FLOORSTATES} = join( ",", @FLOORSTATES ); $hash->{SECTIONSTATES} = join( ",", @SECTIONSTATES );
} }
elsif ( $hash->{FLOORSTATES} ) { elsif ( $hash->{SECTIONSTATES} ) {
delete $hash->{FLOORSTATES}; delete $hash->{SECTIONSTATES};
} }
if ( $hash->{FLOORSTATES} ) { if ( $hash->{SECTIONSTATES} ) {
$ret .= "," if ($ret); $ret .= "," if ($ret);
$ret .= $hash->{FLOORSTATES}; $ret .= $hash->{SECTIONSTATES};
} }
} }
if ( $hash->{TYPE} eq "HOMESTATE" || $hash->{TYPE} eq "FLOORSTATE" ) { if ( $hash->{TYPE} eq "HOMESTATE" || $hash->{TYPE} eq "SECTIONSTATE" ) {
my @ROOMSTATES; my @ROOMSTATES;
foreach ( devspec2array("TYPE=ROOMSTATE") ) { foreach ( devspec2array("TYPE=ROOMSTATE") ) {
@ -1007,9 +1009,9 @@ sub HOMESTATEtk_findHomestateSlaves($;$) {
split( /,/, $defs{$_}{HOMESTATES} ) split( /,/, $defs{$_}{HOMESTATES} )
) )
|| ( || (
defined( $defs{$_}{FLOORSTATES} ) defined( $defs{$_}{SECTIONSTATES} )
&& grep { $hash->{NAME} eq $_ } && grep { $hash->{NAME} eq $_ }
split( /,/, $defs{$_}{FLOORSTATES} ) split( /,/, $defs{$_}{SECTIONSTATES} )
) )
); );
push @ROOMSTATES, $_; push @ROOMSTATES, $_;
@ -1163,7 +1165,7 @@ sub HOMESTATEtk_UpdateReadings (@) {
my $wayhome = 0; my $wayhome = 0;
my $wayhomeDelayed = 0; my $wayhomeDelayed = 0;
my $wakeup = 0; my $wakeup = 0;
foreach my $internal ( "RESIDENTS", "FLOORSTATES", "ROOMSTATES" ) { foreach my $internal ( "RESIDENTS", "SECTIONSTATES", "ROOMSTATES" ) {
next unless ( $hash->{$internal} ); next unless ( $hash->{$internal} );
foreach my $presenceDev ( split( /,/, $hash->{$internal} ) ) { foreach my $presenceDev ( split( /,/, $hash->{$internal} ) ) {
my $state = ReadingsVal( $presenceDev, "state", "gone" ); my $state = ReadingsVal( $presenceDev, "state", "gone" );
@ -1184,7 +1186,7 @@ sub HOMESTATEtk_UpdateReadings (@) {
} }
$state_home = 1 $state_home = 1
unless ( $hash->{RESIDENTS} unless ( $hash->{RESIDENTS}
|| $hash->{FLOORSTATES} || $hash->{SECTIONSTATES}
|| $hash->{ROOMSTATES} ); || $hash->{ROOMSTATES} );
# autoMode # autoMode

View File

@ -1131,19 +1131,18 @@ sub IsHoliday(;$) {
# Get current stage of the daytime based on temporal hours # Get current stage of the daytime based on temporal hours
# https://de.wikipedia.org/wiki/Temporale_Stunden # https://de.wikipedia.org/wiki/Temporale_Stunden
sub GetDaytime(;$$$$) { sub GetDaytime(;$$$$) {
my ( $time, $totalTemporalHours, $lang, @srParams ) = @_; my ( $time, $totalTemporalHours, $lang, $params ) = @_;
$lang = ( $lang = (
$main::attr{global}{language} $main::attr{global}{language}
? $main::attr{global}{language} ? $main::attr{global}{language}
: "EN" : "EN"
) unless ($lang); ) unless ($lang);
my $ret = ref($time) eq "HASH" ? $time : _time( $time, $lang, 1 ); my $ret = ref($time) eq "HASH" ? $time : _time( $time, $lang, 1, $params );
return undef unless ( ref($ret) eq "HASH" ); return undef unless ( ref($ret) eq "HASH" );
$ret->{daytimeStages} = $totalTemporalHours $ret->{daytimeStages} = $totalTemporalHours
&& $totalTemporalHours =~ m/^\d+$/ ? $totalTemporalHours : 12; && $totalTemporalHours =~ m/^\d+$/ ? $totalTemporalHours : 12;
$ret->{srParams} = $ret{srParams} ? $ret{srParams} : [];
# TODO: consider srParams # TODO: consider srParams
$ret->{sunrise} = main::sunrise_abs_dat( $ret->{time_t} ); $ret->{sunrise} = main::sunrise_abs_dat( $ret->{time_t} );
@ -1166,7 +1165,7 @@ sub GetDaytime(;$$$$) {
$ret->{daytimeStage_float} = $ret->{daytimeStage_float} =
$ret->{daytimeRel_s} / $ret->{daytimeStageLn_s}; $ret->{daytimeRel_s} / $ret->{daytimeStageLn_s};
$ret->{daytimeStage} = $ret->{daytimeStage} =
int( $ret->{daytimeRel_s} / $ret->{daytimeStageLn_s} + 1 ); int( ( ( $ret->{daytimeRel_s} + 1 ) / $ret->{daytimeStageLn_s} ) + 1 );
$ret->{daytimeStage} = 0 $ret->{daytimeStage} = 0
if ( $ret->{daytimeStage} < 1 if ( $ret->{daytimeStage} < 1
|| $ret->{daytimeStage} > $ret->{daytimeStages} ); || $ret->{daytimeStage} > $ret->{daytimeStages} );
@ -1178,11 +1177,15 @@ sub GetDaytime(;$$$$) {
#$ret = GetSeasonSocial( $ret, $lang ); #TODO https://de.wikipedia.org/wiki/F%C3%BCnfte_Jahreszeit #$ret = GetSeasonSocial( $ret, $lang ); #TODO https://de.wikipedia.org/wiki/F%C3%BCnfte_Jahreszeit
# change midnight event when season changes # change midnight event when season changes
$ret->{events}{ $ret->{midnight_t} }{VALUE} = 1
if ( $ret->{seasonMeteoChng} && $ret->{seasonMeteoChng} == 1 );
$ret->{events}{ $ret->{midnight_t} }{DESC} .= $ret->{events}{ $ret->{midnight_t} }{DESC} .=
", Begin meteorological $ret->{seasonMeteo_long} season" ", Begin meteorological $ret->{seasonMeteo_long} season"
if ( $ret->{seasonMeteoChng} && $ret->{seasonMeteoChng} == 1 ); if ( $ret->{seasonMeteoChng} && $ret->{seasonMeteoChng} == 1 );
$ret->{events}{ $ret->{midnight_t} }{VALUE} = 2
if ( $ret->{seasonAstroChng} && $ret->{seasonAstroChng} == 1 );
$ret->{events}{ $ret->{midnight_t} }{DESC} .= $ret->{events}{ $ret->{midnight_t} }{DESC} .=
", Begin astrological $ret->{seasonAstro_long} season" ", Begin astronomical $ret->{seasonAstro_long} season"
if ( $ret->{seasonAstroChng} && $ret->{seasonAstroChng} == 1 ); if ( $ret->{seasonAstroChng} && $ret->{seasonAstroChng} == 1 );
# calculate daytime from daytimeStage, season and DST # calculate daytime from daytimeStage, season and DST
@ -1204,7 +1207,7 @@ sub GetDaytime(;$$$$) {
# when no relation was found # when no relation was found
unless ( defined( $ret->{daytime} ) || $ds > -1 ) { unless ( defined( $ret->{daytime} ) || $ds > -1 ) {
# assume evening after sunset # assume midevening after sunset
if ( $ret->{time_s} >= $ret->{sunset_s} ) { if ( $ret->{time_s} >= $ret->{sunset_s} ) {
$ret->{daytime} = 5; $ret->{daytime} = 5;
} }
@ -1240,15 +1243,15 @@ sub GetDaytime(;$$$$) {
# #
# Midnight # Midnight
$ret->{events}{ $ret->{midnight_t} }{TYPE} = "dayshift";
$ret->{events}{ $ret->{midnight_t} }{TIME} = $ret->{events}{ $ret->{midnight_t} }{TIME} =
main::FmtDateTime( $ret->{midnight_t} ); main::FmtDateTime( $ret->{midnight_t} );
$ret->{events}{ $ret->{midnight_t} }{DESC} = $ret->{events}{ $ret->{midnight_t} }{DESC} =
"Begin night time and new calendar day"; "Begin of night time and new calendar day";
$ret->{events}{ $ret->{1}{midnight_t} }{TIME} = $ret->{events}{ $ret->{1}{midnight_t} }{TYPE} = "dayshift";
main::FmtDateTime( $ret->{1}{midnight_t} ); $ret->{events}{ $ret->{1}{midnight_t} }{TIME} = $ret->{date} . " 24:00:00";
$ret->{events}{ $ret->{1}{midnight_t} }{TIME} =~ s/00:00:00/24:00:00/;
$ret->{events}{ $ret->{1}{midnight_t} }{DESC} = $ret->{events}{ $ret->{1}{midnight_t} }{DESC} =
"End calendar day and begin night time"; "End of calendar day and begin night time";
# Holidays # Holidays
$ret->{events}{ $ret->{midnight_t} }{DESC} .= $ret->{events}{ $ret->{midnight_t} }{DESC} .=
@ -1262,15 +1265,16 @@ sub GetDaytime(;$$$$) {
#FIXME TODO #FIXME TODO
if ( $ret->{dstchange} && $ret->{dstchange} == 1 ) { if ( $ret->{dstchange} && $ret->{dstchange} == 1 ) {
my $t = $ret->{midnight_t} + 2 * 60 * 60; my $t = $ret->{midnight_t} + 2 * 60 * 60;
$ret->{events}{$t}{TYPE} = "dstshift";
$ret->{events}{$t}{VALUE} = $ret->{isdst};
$ret->{events}{$t}{TIME} = main::FmtDateTime($t); $ret->{events}{$t}{TIME} = main::FmtDateTime($t);
$ret->{events}{$t}{DESC} = "Begin standard time (-1h)" $ret->{events}{$t}{DESC} = "Begin of standard time (-1h)"
unless ( $ret->{isdst} ); unless ( $ret->{isdst} );
$ret->{events}{$t}{DESC} = "Begin daylight saving time (+1h)" $ret->{events}{$t}{DESC} = "Begin of daylight saving time (+1h)"
if ( $ret->{isdst} ); if ( $ret->{isdst} );
} }
# daytime stage event forecast for today # daytime stage event forecast for today
#TODO add daytime to desc when it changes
my $i = 1; my $i = 1;
my $b = $ret->{sunrise_t}; my $b = $ret->{sunrise_t};
while ( $i <= $ret->{daytimeStages} + 1 ) { while ( $i <= $ret->{daytimeStages} + 1 ) {
@ -1290,14 +1294,22 @@ sub GetDaytime(;$$$$) {
my $t = int( $b + 0.5 ); my $t = int( $b + 0.5 );
$ret->{events}{$t}{TIME} = main::FmtDateTime($t); $ret->{events}{$t}{TIME} = main::FmtDateTime($t);
if ( $i == $ret->{daytimeStages} + 1 ) { if ( $i == $ret->{daytimeStages} + 1 ) {
$ret->{events}{$t}{DESC} = "Begin midevening time"; $ret->{events}{$t}{TYPE} = "daytime";
$ret->{events}{$t}{VALUE} = "midevening";
$ret->{events}{$t}{DESC} =
"End of daytime";
} }
else { else {
$ret->{events}{$t}{DESC} = "Begin daytime stage $i" $ret->{events}{$t}{TYPE} = "daytimeStage";
$ret->{events}{$t}{VALUE} = $i;
$ret->{events}{$t}{DESC} = "Begin of daytime stage $i"
unless ($daytime); unless ($daytime);
if ( defined($daytime) ) {
$ret->{events}{$t}{TYPE} = "daytime";
$ret->{events}{$t}{VALUE} = $daytimes{en}[$daytime];
$ret->{events}{$t}{DESC} = $ret->{events}{$t}{DESC} =
"Begin $daytimes{en}[$daytime] time and daytime stage $i" "Begin of $daytimes{en}[$daytime] time and daytime stage $i";
if ( defined($daytime) ); }
} }
$i++; $i++;
$b += $ret->{daytimeStageLn_s}; $b += $ret->{daytimeStageLn_s};
@ -1607,8 +1619,8 @@ sub _round($;$) {
sub _time(;$$$); sub _time(;$$$);
sub _time(;$$$) { sub _time(;$$$$) {
my ( $time, $lang, $dayOffset ) = @_; my ( $time, $lang, $dayOffset, $params ) = @_;
$dayOffset = 1 if ( !defined($dayOffset) || $dayOffset !~ /^-?\d+$/ ); $dayOffset = 1 if ( !defined($dayOffset) || $dayOffset !~ /^-?\d+$/ );
$lang = ( $lang = (
$main::attr{global}{language} $main::attr{global}{language}
@ -1622,6 +1634,7 @@ sub _time(;$$$) {
my %ret; my %ret;
$ret{time_t} = $time if ($time); $ret{time_t} = $time if ($time);
$ret{time_t} = time unless ($time); $ret{time_t} = time unless ($time);
$ret{params} = $params if ($params);
my @t = localtime( $ret{time_t} ); my @t = localtime( $ret{time_t} );
( (