587 lines
14 KiB
Perl
587 lines
14 KiB
Perl
use warnings "all";
|
|
use strict;
|
|
use Time::Local;
|
|
use DateTime;
|
|
use Date::Calc;
|
|
use Date::Manip;
|
|
use POSIX qw(strftime);
|
|
use config;
|
|
|
|
package time;
|
|
use Data::Dumper;
|
|
use utf8;
|
|
|
|
require Exporter;
|
|
our @ISA = qw(Exporter);
|
|
our @EXPORT_OK = qw(
|
|
format_datetime format_time
|
|
date_format time_format
|
|
datetime_to_time time_to_datetime time_to_date
|
|
datetime_to_date
|
|
add_days_to_datetime add_hours_to_datetime add_minutes_to_datetime
|
|
add_days_to_date
|
|
datetime_to_array date_to_array array_to_date array_to_datetime array_to_time array_to_time_hm
|
|
date_cond time_cond check_date check_time check_datetime check_year_month
|
|
datetime_to_rfc822 get_datetime datetime_to_utc datetime_to_utc_datetime
|
|
get_duration get_duration_seconds
|
|
get_durations get_names get_all_names get_weekdays weekday_index
|
|
$names
|
|
);
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] );
|
|
|
|
our $names={
|
|
'de' =>{
|
|
months =>['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
|
|
months_abbr =>['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],
|
|
weekdays =>['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'],
|
|
weekdays_abbr =>['Mo','Di','Mi','Do','Fr','Sa','So'],
|
|
},
|
|
'en' =>{
|
|
months =>['January','February','March','April','May','June','Jule','August','September','October','November','December'],
|
|
months_abbr =>['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
|
|
weekdays =>['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
|
|
weekdays_abbr =>['Mo','Tu','We','Th','Fr','Sa','Su'],
|
|
},
|
|
};
|
|
|
|
our $durations=[
|
|
0, 5,10,15,20,30,40,45,50,60,70,75,80,90,100,105,110,115,120,135,150,165,180,195,210,225,240,300,360,420,480,540,600,660,720,1440
|
|
];
|
|
|
|
sub get_names{
|
|
my $language=shift||'en';
|
|
return $time::names->{$language};
|
|
}
|
|
|
|
sub get_all_names{
|
|
return $time::names;
|
|
}
|
|
|
|
sub get_durations{
|
|
return $time::durations;
|
|
}
|
|
|
|
#TODO: build from datenames
|
|
our $weekday_index={
|
|
'0' => 0,
|
|
'1' => 1,
|
|
'2' => 2,
|
|
'3' => 3,
|
|
'4' => 4,
|
|
'5' => 5,
|
|
'6' => 6,
|
|
'Mo'=> 0,
|
|
'Tu'=> 1,
|
|
'Di'=> 1,
|
|
'We'=> 2,
|
|
'Mi'=> 2,
|
|
'Th'=> 3,
|
|
'Do'=> 3,
|
|
'Fr'=> 4,
|
|
'Sa'=> 5,
|
|
'Su'=> 6,
|
|
'So'=> 6
|
|
};
|
|
|
|
sub get_weekdays{
|
|
return{
|
|
0 => 0,
|
|
1 => 1,
|
|
2 => 2,
|
|
3 => 3,
|
|
4 => 4,
|
|
5 => 5,
|
|
6 => 6,
|
|
'Mo'=>0,
|
|
'Tu'=>1,
|
|
'Di'=>1,
|
|
'We'=>2,
|
|
'Mi'=>2,
|
|
'Th'=>3,
|
|
'Do'=>3,
|
|
'Fr'=>4,
|
|
'Sa'=>5,
|
|
'Su'=>6,
|
|
'So'=>6
|
|
};
|
|
}
|
|
|
|
|
|
#deprecated, for wordpress sync
|
|
sub format_datetime{
|
|
my $datetime=shift;
|
|
return $datetime if ($datetime eq '');
|
|
return add_hours_to_datetime($datetime,0);
|
|
};
|
|
|
|
#deprecated
|
|
sub format_time{
|
|
my $t=$_[0];
|
|
|
|
my $year =$t->[5]+1900;
|
|
my $month =$t->[4]+1;
|
|
$month ='0'.$month if(length($month)==1);
|
|
|
|
my $day =$t->[3];
|
|
$day ='0'.$day if(length($day)==1);
|
|
|
|
|
|
my $hour =$t->[2];
|
|
$hour ='0'.$hour if(length($hour)==1);
|
|
|
|
my $minute =$t->[1];
|
|
$minute ='0'.$minute if(length($minute)==1);
|
|
|
|
return [$day,$month,$year,$hour,$minute];
|
|
};
|
|
|
|
|
|
# convert datetime to unix time
|
|
sub datetime_to_time{
|
|
my $datetime=$_[0];
|
|
# print $datetime."\n";
|
|
if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)[T\s](\d+)\:(\d+)(\:(\d+))?/){
|
|
my $year=$1;
|
|
my $month=$2-1;
|
|
my $day=$3;
|
|
my $hour=$4;
|
|
my $minute=$5;
|
|
my $second=$8||0;
|
|
return Time::Local::timelocal($second,$minute,$hour,$day,$month,$year);
|
|
|
|
}else{
|
|
print STDERR "datetime_to_time: no valid date time found! ($datetime )\n";
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
#get rfc822 datetime string from datetime string
|
|
sub datetime_to_rfc822{
|
|
my $datetime=$_[0];
|
|
my $time=datetime_to_time($datetime);
|
|
return POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time));
|
|
}
|
|
|
|
#get seconds from epoch
|
|
sub datetime_to_utc{
|
|
my $datetime=shift;
|
|
my $time_zone=shift;
|
|
$datetime=get_datetime($datetime, $time_zone);
|
|
return $datetime->epoch();
|
|
}
|
|
|
|
# get full utc datetime including timezone offset
|
|
sub datetime_to_utc_datetime{
|
|
my $datetime=shift;
|
|
my $time_zone=shift;
|
|
$datetime=get_datetime($datetime, $time_zone);
|
|
return $datetime->format_cldr("yyyy-MM-ddTHH:mm:ssZZZZZ");
|
|
}
|
|
|
|
|
|
|
|
#add hours to datetime string
|
|
sub add_hours_to_datetime{
|
|
my $datetime=shift;
|
|
my $hours=shift;
|
|
return time_to_datetime(datetime_to_time($datetime)+(3600*$hours));
|
|
};
|
|
|
|
#add minutes to datetime string
|
|
sub add_minutes_to_datetime{
|
|
my $datetime=shift;
|
|
my $minutes=shift;
|
|
return time_to_datetime(datetime_to_time($datetime)+(60*$minutes));
|
|
};
|
|
|
|
#add days to datetime string
|
|
sub add_days_to_datetime{
|
|
my $datetime=shift;
|
|
my $days=shift;
|
|
my $time=datetime_to_array($datetime);
|
|
#print STDERR Dumper($time);
|
|
($time->[0], $time->[1], $time->[2]) =Date::Calc::Add_Delta_Days($time->[0]+0, $time->[1]+0, $time->[2]+0, $days);
|
|
return array_to_datetime($time);
|
|
}
|
|
|
|
sub add_days_to_date{
|
|
my $datetime=shift;
|
|
my $days=shift;
|
|
my $date=date_to_array($datetime);
|
|
($date->[0], $date->[1], $date->[2]) =Date::Calc::Add_Delta_Days($date->[0]+0, $date->[1]+0, $date->[2]+0, $days);
|
|
return array_to_date($date);
|
|
}
|
|
|
|
# convert unix time to datetime format
|
|
sub time_to_datetime{
|
|
my $time=shift;
|
|
$time=time() unless((defined $time) && ($time ne''));
|
|
my @t=localtime($time);
|
|
return sprintf('%04d-%02d-%02d %02d:%02d:%02d', $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);
|
|
};
|
|
|
|
# convert unix time to date format
|
|
sub time_to_date{
|
|
my $time=shift;
|
|
$time=time() unless((defined $time) && ($time ne''));
|
|
my @t=localtime($time);
|
|
return sprintf('%04d-%02d-%02d', $t[5]+1900, $t[4]+1, $t[3]);
|
|
};
|
|
|
|
# convert datetime to a array of date/time values
|
|
sub datetime_to_array{
|
|
my $datetime=$_[0]||'';
|
|
if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)([T\s]+(\d+)\:(\d+)(\:(\d+))?)?/){
|
|
my $year=$1;
|
|
my $month=$2;
|
|
my $day=$3;
|
|
my $hour=$5||'00';
|
|
my $minute=$6||'00';
|
|
my $second=$8||'00';
|
|
return [$year,$month,$day,$hour,$minute,$second];
|
|
}
|
|
return undef;
|
|
};
|
|
|
|
# convert datetime to date
|
|
sub datetime_to_date{
|
|
my $datetime=$_[0]||'';
|
|
if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){
|
|
my $year=$1;
|
|
my $month=$2;
|
|
my $day=$3;
|
|
return sprintf("%04d-%02d-%02d",$year,$month,$day);
|
|
}
|
|
return undef;
|
|
};
|
|
|
|
#convert datetime array or single value to datetime string
|
|
sub array_to_datetime{
|
|
my $date =shift;
|
|
if(ref($date)eq'ARRAY'){
|
|
return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $date->[0], $date->[1], $date->[2], $date->[3], $date->[4], $date->[5]);
|
|
}
|
|
my $month =shift;
|
|
my $day =shift;
|
|
my $hour =shift||'0';
|
|
my $minute =shift||'0';
|
|
my $second =shift||'0';
|
|
return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $date, $month, $day, $hour, $minute, $second);
|
|
}
|
|
|
|
#convert date array or single values to date string
|
|
sub array_to_date{
|
|
my $date =shift;
|
|
if(ref($date)eq'ARRAY'){
|
|
return sprintf("%04d-%02d-%02d", $date->[0], $date->[1], $date->[2]);
|
|
}
|
|
my $month=shift;
|
|
my $day =shift;
|
|
return sprintf("%04d-%02d-%02d", $date, $month, $day);
|
|
}
|
|
|
|
sub array_to_time{
|
|
my $date =shift;
|
|
if(ref($date)eq'ARRAY'){
|
|
return sprintf("%02d:%02d:%02d", $date->[3], $date->[4], $date->[5]);
|
|
}
|
|
my $minute = shift||0;
|
|
my $second = shift||0;
|
|
return sprintf("%02d:%02d:%02d", $date, $minute, $second);
|
|
}
|
|
|
|
sub array_to_time_hm{
|
|
my $date =shift;
|
|
if(ref($date)eq'ARRAY'){
|
|
return sprintf("%02d:%02d", $date->[3], $date->[4]);
|
|
}
|
|
my $minute = shift||0;
|
|
return sprintf("%02d:%02d", $date, $minute);
|
|
}
|
|
|
|
|
|
# get number of days between two days
|
|
sub days_between{
|
|
my $today=$_[0];
|
|
my $date=$_[1];
|
|
my $delta_days=eval{Date::Calc::Delta_Days(
|
|
$today->[0],$today->[1],$today->[2],
|
|
$date->[0], $date->[1], $date->[2]
|
|
)};
|
|
return $delta_days;
|
|
}
|
|
|
|
sub dayOfYear{
|
|
my $datetime=$_[0];
|
|
if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){
|
|
my $year = $1;
|
|
my $month = $2;
|
|
my $day = $3;
|
|
return Date::Calc::Day_of_Year($year,$month,$day);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
# get duration in minutes
|
|
sub get_duration{
|
|
my $start = shift;
|
|
my $end = shift;
|
|
my $timezone= shift;
|
|
$start=time::get_datetime($start, $timezone);
|
|
$end =time::get_datetime($end, $timezone);
|
|
my $duration=$end->epoch()-$start->epoch();
|
|
return $duration/60;
|
|
}
|
|
|
|
# get duration in seconds
|
|
sub get_duration_seconds{
|
|
my $start = shift;
|
|
my $end = shift;
|
|
my $timezone= shift||'UTC';
|
|
$start=time::get_datetime($start, $timezone);
|
|
$end =time::get_datetime($end, $timezone);
|
|
my $duration=$end->epoch()-$start->epoch();
|
|
return $duration;
|
|
}
|
|
|
|
# convert date string to a array of date values
|
|
sub date_to_array{
|
|
my $datetime=$_[0];
|
|
if ($datetime=~/(\d\d\d\d)\-(\d+)\-(\d+)/){
|
|
my $year = $1;
|
|
my $month = $2;
|
|
my $day = $3;
|
|
return [$year,$month,$day];
|
|
}
|
|
return undef;
|
|
};
|
|
|
|
# parse date string and return date string
|
|
# pass 'today', return '' on parse error
|
|
sub date_cond{
|
|
my $date=shift;
|
|
|
|
return '' if ($date eq'');
|
|
if ($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){
|
|
my $year = $1;
|
|
my $month = $2;
|
|
my $day = $3;
|
|
return sprintf("%04d-%02d-%02d", $year, $month, $day);
|
|
}
|
|
return 'today' if ($date eq 'today');
|
|
return '';
|
|
};
|
|
|
|
#parse time and return time string hh:mm:ss
|
|
#return hh:00 if time is 'now'
|
|
sub time_cond{
|
|
my $time = shift;
|
|
|
|
return '' if ($time eq'');
|
|
if ($time=~/(\d\d?)\:(\d\d?)(\:(\d\d))?/){
|
|
my $hour=$1;
|
|
my $minute=$2;
|
|
my $second=$4||'00';
|
|
return sprintf("%02d:%02d:%02d", $hour, $minute, $second);
|
|
}
|
|
if ($time eq 'now'){
|
|
my $date=datetime_to_array(time_to_datetime(time()));
|
|
my $hour=$date->[3]-2;
|
|
$hour=0 if ($hour<0);
|
|
$time=sprintf("%02d:00",$hour);
|
|
return $time;
|
|
}
|
|
return '';
|
|
};
|
|
|
|
#parse date and time string and return yyyy-mm-ddThh:mm:ss
|
|
sub datetime_cond{
|
|
my $datetime = shift;
|
|
|
|
return '' if ($datetime eq'');
|
|
(my $date,my $time)=split /[ T]/,$datetime;
|
|
$date=time::date_cond($date);
|
|
return '' if ($date eq'');
|
|
$time=time::time_cond($time);
|
|
return '' if ($time eq'');
|
|
|
|
return $date.'T'.$time;
|
|
}
|
|
|
|
sub check_date{
|
|
my $date=shift;
|
|
|
|
return "" if((!defined $date) || ($date eq ''));
|
|
if($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){
|
|
return $1.'-'.$2.'-'.$3;
|
|
}elsif($date=~/(\d\d?)\.(\d\d?)\.(\d\d\d\d)/){
|
|
return $3.'-'.$2.'-'.$1;
|
|
}
|
|
return $date if ($date eq'today' || $date eq'tomorrow' || $date eq'yesterday');
|
|
return -1;
|
|
#error("no valid date format given!");
|
|
};
|
|
|
|
sub check_time{
|
|
my $time=shift;
|
|
return "" if((!defined $time) || ($time eq ''));
|
|
return $time if(($time eq 'now') || ($time eq 'future'));
|
|
if($time=~/(\d\d?)\:(\d\d?)/){
|
|
return $1.':'.$2
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
sub check_datetime{
|
|
my $date=shift;
|
|
|
|
return "" if((!defined $date) || ($date eq ''));
|
|
if($date=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)[T ](\d\d?)\:(\d\d?)/){
|
|
return sprintf("%04d-%02d-%02dT%02d:%02d",$1,$2,$3,$4,$5);
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
sub check_year_month{
|
|
my $date=shift;
|
|
return -1 unless(defined $date);
|
|
return $date if($date eq '');
|
|
if($date=~/(\d\d\d\d)\-(\d\d?)/){
|
|
return $1.'-'.$2.'-'.$3;
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
#TODO: remove config dependency
|
|
sub date_time_format{
|
|
my $datetime=shift;
|
|
my $language=shift || $config::config->{date}->{language} || 'en';
|
|
if (defined $datetime && $datetime=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)[\sT](\d\d?\:\d\d?)/){
|
|
my $time=$4;
|
|
my $day=$3;
|
|
my $month=$2;
|
|
my $year=$1;
|
|
|
|
$month=$time::names->{$language}->{months_abbr}->[$month-1]||'';
|
|
return "$day. $month $year $time";
|
|
}
|
|
return $datetime;
|
|
}
|
|
|
|
#format datetime to date string
|
|
#TODO: remove config dependency
|
|
sub date_format{
|
|
my $datetime=shift;
|
|
my $language=shift || $config::config->{date}->{language} || 'en';
|
|
|
|
if (defined $datetime && $datetime=~/(\d\d\d\d)\-(\d\d?)\-(\d\d?)/){
|
|
my $day=$3;
|
|
my $month=$2;
|
|
my $year=$1;
|
|
$month=$time::names->{$language}->{months_abbr}->[$month-1]||'';
|
|
return "$day. $month $year";
|
|
}
|
|
return $datetime;
|
|
};
|
|
|
|
#format datetime to time string
|
|
sub time_format{
|
|
my $datetime=shift;
|
|
if (defined $datetime && $datetime=~/(\d\d?\:\d\d?)/){
|
|
return $1;
|
|
}
|
|
return $datetime;
|
|
};
|
|
|
|
#get offset from given time_zone
|
|
sub utc_offset{
|
|
my $time_zone=shift;
|
|
|
|
$a=DateTime->now();
|
|
$a->set_time_zone($time_zone);
|
|
return $a->strftime("%z");
|
|
}
|
|
|
|
#get weekday from (yyyy,mm,dd)
|
|
sub weekday{
|
|
my ($year,$month,$day)=@_;
|
|
my $time = Time::Local::timelocal(0,0,0,$day,$month-1,$year);
|
|
return (localtime($time))[6];
|
|
}
|
|
|
|
#get current date, related to starting day_starting_hour
|
|
#TODO: remove config dependency
|
|
sub get_event_date{
|
|
my $config=shift;
|
|
$config=$config::config unless defined $config;
|
|
|
|
my $datetime=time::time_to_datetime(time());
|
|
my $hour=(time::datetime_to_array($datetime))->[3];
|
|
#today: between 0:00 and starting_hour show last day
|
|
if ($hour < $config->{date}->{day_starting_hour}){
|
|
my $date=time::datetime_to_array(time::add_hours_to_datetime($datetime,-24));
|
|
return $date->[0].'-'.$date->[1].'-'.$date->[2];
|
|
}else{
|
|
#today: between starting_hour and end of day show current day
|
|
my $date=time::datetime_to_array(time::time_to_datetime(time()));
|
|
return $date->[0]."-".$date->[1]."-".$date->[2];
|
|
}
|
|
}
|
|
|
|
#get datetime object from datetime string
|
|
sub get_datetime{
|
|
my $datetime=shift;
|
|
my $timezone=shift;
|
|
|
|
return unless defined $datetime;
|
|
return if $datetime eq '';
|
|
my @l = @{time::datetime_to_array($datetime)};
|
|
return undef if scalar(@l)==0;
|
|
|
|
# catch invalid datees
|
|
$datetime=undef;
|
|
eval{
|
|
$datetime=DateTime->new(
|
|
year =>$l[0],
|
|
month =>$l[1],
|
|
day =>$l[2],
|
|
hour =>$l[3],
|
|
minute =>$l[4],
|
|
second =>$l[5],
|
|
time_zone=> $timezone
|
|
);
|
|
};
|
|
return undef unless defined $datetime;
|
|
$datetime->set_locale('de_DE');
|
|
return $datetime;
|
|
}
|
|
|
|
#get list of nth weekday in month from start to end
|
|
sub get_nth_weekday_in_month{
|
|
my $start=shift; # datetime string
|
|
my $end=shift; # datetime string
|
|
my $nth=shift; # every nth week of month
|
|
my $weekday=shift; # weekday [0..6,'Mo'-'Su','Mo'-'Fr']
|
|
|
|
my $weekdays=time::get_weekdays();
|
|
$weekday=$weekdays->{$weekday+1};
|
|
|
|
my $dates=[];
|
|
if ($start=~/(\d\d\d\d)-(\d\d)-(\d\d)[ T](\d\d)\:(\d\d)/){
|
|
my $hour=int($4);
|
|
my $min=int($5);
|
|
my $sec=0;
|
|
my @date = Date::Manip::ParseRecur("0:1*$nth:$weekday:$hour:$min:$sec", "", $start, $end);
|
|
for my $date (@date){
|
|
if ($date=~/(\d\d\d\d)(\d\d)(\d\d)(\d\d)\:(\d\d)\:(\d\d)/){
|
|
push @$dates,"$1-$2-$3 $4:$5:$6";
|
|
}
|
|
}
|
|
}
|
|
return $dates;
|
|
}
|
|
|
|
#do not delete last line!
|
|
1;
|