620 lines
17 KiB
Perl
620 lines
17 KiB
Perl
package time;
|
|
|
|
use strict;
|
|
use warnings;
|
|
no warnings 'redefine';
|
|
use utf8;
|
|
|
|
use Time::Local();
|
|
use DateTime();
|
|
use Date::Calc();
|
|
use Date::Manip();
|
|
use POSIX qw(strftime);
|
|
use Data::Dumper;
|
|
|
|
use config();
|
|
|
|
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
|
|
getDurations getWeekdayIndex getWeekdayNames getWeekdayNamesShort getMonthNames getMonthNamesShort
|
|
);
|
|
|
|
my $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' ],
|
|
},
|
|
};
|
|
|
|
|
|
# map starting with monday=0
|
|
my $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
|
|
};
|
|
|
|
my $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 getDurations() {
|
|
return $DURATIONS;
|
|
}
|
|
|
|
sub getWeekdayNames(;$) {
|
|
my ($language) = @_;
|
|
$language ||= 'en';
|
|
return $NAMES->{$language}->{weekdays};
|
|
}
|
|
|
|
sub getWeekdayNamesShort(;$) {
|
|
my ($language) = @_;
|
|
$language ||= 'en';
|
|
return $NAMES->{$language}->{weekdays_abbr};
|
|
}
|
|
|
|
sub getMonthNames(;$) {
|
|
my ($language) = @_;
|
|
$language ||= 'en';
|
|
return $NAMES->{$language}->{months};
|
|
}
|
|
|
|
sub getMonthNamesShort(;$) {
|
|
my ($language) = @_;
|
|
$language ||= 'en';
|
|
return $NAMES->{$language}->{months_abbr};
|
|
}
|
|
|
|
|
|
sub getWeekdayIndex(;$) {
|
|
my ($weekday) = @_;
|
|
$weekday ||= '';
|
|
return $WEEKDAY_INDEX->{$weekday};
|
|
}
|
|
|
|
# map starting with monday=1
|
|
sub getWeekdays {
|
|
return {
|
|
1 => 1,
|
|
2 => 2,
|
|
3 => 3,
|
|
4 => 4,
|
|
5 => 5,
|
|
6 => 6,
|
|
7 => 7,
|
|
'Mo' => 1,
|
|
'Tu' => 2,
|
|
'Di' => 2,
|
|
'We' => 3,
|
|
'Mi' => 3,
|
|
'Th' => 4,
|
|
'Do' => 4,
|
|
'Fr' => 5,
|
|
'Sa' => 6,
|
|
'Su' => 7,
|
|
'So' => 7
|
|
};
|
|
}
|
|
|
|
#deprecated, for wordpress sync
|
|
sub format_datetime(;$) {
|
|
my ($datetime) = @_;
|
|
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];
|
|
|
|
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 ) || print STDERR "datetime_to_time: no valid date time found! ($datetime)\n";
|
|
|
|
} 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, $time_zone) = @_;
|
|
$datetime = get_datetime( $datetime, $time_zone );
|
|
return $datetime->epoch();
|
|
}
|
|
|
|
# get full utc datetime including timezone offset
|
|
sub datetime_to_utc_datetime($$) {
|
|
my ($datetime, $time_zone) = @_;
|
|
$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, $hours) = @_;
|
|
$hours = 0 unless defined $hours;
|
|
return time_to_datetime( datetime_to_time($datetime) + ( 3600 * $hours ) );
|
|
}
|
|
|
|
#add minutes to datetime string
|
|
sub add_minutes_to_datetime($;$) {
|
|
my ($datetime, $minutes) = @_;
|
|
$minutes = 0 unless defined $minutes;
|
|
return time_to_datetime( datetime_to_time($datetime) + ( 60 * $minutes ) );
|
|
}
|
|
|
|
#add days to datetime string
|
|
sub add_days_to_datetime($;$) {
|
|
my ($datetime, $days) = @_;
|
|
$days = 0 unless defined $days;
|
|
my $time = datetime_to_array($datetime);
|
|
|
|
( $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, $days) = @_;
|
|
$days = 0 unless defined $days;
|
|
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) = @_;
|
|
$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) = @_;
|
|
$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) = @_;
|
|
$datetime ||= '';
|
|
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, $month, $day, $hour, $minute, $second) = @_;
|
|
|
|
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] );
|
|
}
|
|
|
|
$hour ||= '0';
|
|
$minute ||= '0';
|
|
$second ||= '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, $month, $day) = @_;
|
|
if ( ref($date) eq 'ARRAY' ) {
|
|
return sprintf( "%04d-%02d-%02d", $date->[0], $date->[1], $date->[2] );
|
|
}
|
|
return sprintf( "%04d-%02d-%02d", $date, $month, $day );
|
|
}
|
|
|
|
sub array_to_time(;$) {
|
|
my ($date, $minute, $second) = @_;
|
|
if ( ref($date) eq 'ARRAY' ) {
|
|
return sprintf( "%02d:%02d:%02d", $date->[3], $date->[4], $date->[5] );
|
|
}
|
|
$minute ||= '0';
|
|
$second ||= '0';
|
|
return sprintf( "%02d:%02d:%02d", $date, $minute, $second );
|
|
}
|
|
|
|
sub array_to_time_hm(;$) {
|
|
my ($date, $minute) = @_;
|
|
if ( ref($date) eq 'ARRAY' ) {
|
|
return sprintf( "%02d:%02d", $date->[3], $date->[4] );
|
|
}
|
|
$minute ||= '0';
|
|
return sprintf( "%02d:%02d", $date, $minute );
|
|
}
|
|
|
|
# get number of days between two days
|
|
sub days_between($$) {
|
|
my ($today, $date) = @_;
|
|
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) = @_;
|
|
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, $end, $timezone) = @_;
|
|
$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, $end, $timezone) = @_;
|
|
$timezone ||= 'UTC';
|
|
|
|
unless ( defined $start ) {
|
|
print STDERR "time::get_duration_seconds(): start is missing\n";
|
|
return 0;
|
|
}
|
|
unless ( defined $end ) {
|
|
print STDERR "time::get_duration_seconds(): end is missing\n";
|
|
return 0;
|
|
}
|
|
|
|
$start = time::get_datetime( $start, $timezone );
|
|
$end = time::get_datetime( $end, $timezone );
|
|
unless ( defined $start ) {
|
|
print STDERR "time::get_duration_seconds(): invalid start\n";
|
|
return 0;
|
|
}
|
|
unless ( defined $end ) {
|
|
print STDERR "time::get_duration_seconds(): invalid end\n";
|
|
return 0;
|
|
}
|
|
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) = @_;
|
|
|
|
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) = @_;
|
|
|
|
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) = @_;
|
|
|
|
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) = @_;
|
|
|
|
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) = @_;
|
|
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) = @_;
|
|
|
|
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) = @_;
|
|
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 ($config, $datetime, $language) = @_;
|
|
$language ||= $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::getMonthNamesShort($language)->[ $month - 1 ] || '';
|
|
return "$day. $month $year $time";
|
|
}
|
|
return $datetime;
|
|
}
|
|
|
|
#format datetime to date string
|
|
#TODO: remove config dependency
|
|
sub date_format($$;$) {
|
|
my ($config, $datetime, $language) = @_;
|
|
$language ||= $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::getMonthNamesShort($language)->[ $month - 1 ] || '';
|
|
return "$day. $month $year";
|
|
}
|
|
return $datetime;
|
|
}
|
|
|
|
#format datetime to time string
|
|
sub time_format($) {
|
|
my ($datetime) = @_;
|
|
if ( defined $datetime && $datetime =~ /(\d\d?\:\d\d?)/ ) {
|
|
return $1;
|
|
}
|
|
return $datetime;
|
|
}
|
|
|
|
#get offset from given time_zone
|
|
sub utc_offset($) {
|
|
my ($time_zone) = @_;
|
|
|
|
my $datetime = DateTime->now();
|
|
$datetime->set_time_zone($time_zone);
|
|
return $datetime->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) = @_;
|
|
|
|
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_days_to_datetime( $datetime, -1 ) );
|
|
return join( '-', ( $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 join( '-', ( $date->[0], $date->[1], $date->[2] ) );
|
|
}
|
|
}
|
|
|
|
#get datetime object from datetime string
|
|
sub get_datetime(;$$) {
|
|
my ($datetime, $timezone) = @_;
|
|
|
|
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, $end, $nth, $weekday) = @_;
|
|
#datetime, datetime, every nth week of month, weekday [1..7,'Mo'-'Su','Mo'-'Fr']
|
|
|
|
return [] unless defined $start;
|
|
return [] unless defined $end;
|
|
return [] unless defined $nth;
|
|
return [] unless defined $weekday;
|
|
|
|
my $weekdays = time::getWeekdays();
|
|
return [] unless defined $weekdays->{$weekday};
|
|
$weekday = $weekdays->{$weekday};
|
|
|
|
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;
|