use
vars
qw( @ISA @EXPORT @EXPORT_OK $VERSION )
;
$VERSION
=
"1.12"
;
@ISA
=
qw( Exporter )
;
@EXPORT
=
qw( get_languages
swap_language
parse_date
adjust_future_cutoff
make_it_a_4_digit_year
parse_8_digit_date
parse_6_digit_date
init_special_date_arrays
_date_language_installed
_date_manip_installed
)
;
@EXPORT_OK
=
qw( )
;
my
$global_cutoff_date
= 30;
my
%date_language_installed_languages
;
my
%date_manip_installed_languages
;
BEGIN
{
eval
{
local
$SIG
{__DIE__} =
""
;
my
$loc
=
$INC
{
"Date/Language.pm"
};
$loc
=~ s/[.]pm$//;
my
$search
= File::Spec->catfile (
$loc
,
"*.pm"
);
foreach
my
$f
( bsd_glob (
$search
) ) {
my
$module
= (File::Spec->splitdir(
$f
))[-1];
$module
=~ s/[.]pm$//;
my
%data
= (
Language
=>
$module
,
Module
=>
"Date::Language::${module}"
);
$date_language_installed_languages
{
lc
(
$module
)} = \
%data
;
}
};
}
BEGIN
{
eval
{
local
$SIG
{__DIE__} =
""
;
Date::Manip::Lang::
index
->
import
();
foreach
my
$k
(
sort
keys
%Date::Manip::Lang::index::Lang
) {
my
$mod
=
$Date::Manip::Lang::index::Lang
{
$k
};
my
$lang
= (
$k
eq
$mod
) ?
ucfirst
(
$mod
) :
$mod
;
my
$module
=
"Date::Manip::Lang::${mod}"
;
my
%data
= (
Language
=>
$lang
,
Module
=>
$module
);
$date_manip_installed_languages
{
lc
(
$k
)} = \
%data
;
}
};
}
my
%last_language_edit_flags
;
my
%Months
;
my
%Days
;
BEGIN {
%Months
= (
"january"
=> 1,
"february"
=> 2,
"march"
=> 3,
"april"
=> 4,
"may"
=> 5,
"june"
=> 6,
"july"
=> 7,
"august"
=> 8,
"september"
=> 9,
"october"
=> 10,
"november"
=> 11,
"december"
=> 12,
"jan"
=> 1,
"feb"
=> 2,
"mar"
=> 3,
"apr"
=> 4,
"jun"
=> 6,
"jul"
=> 7,
"aug"
=> 8,
"sep"
=> 9,
"oct"
=> 10,
"nov"
=> 11,
"dec"
=> 12,
"1"
=> 1,
"2"
=> 2,
"3"
=> 3,
"4"
=> 4,
"5"
=> 5,
"6"
=> 6,
"7"
=> 7,
"8"
=> 8,
"9"
=> 9,
"10"
=> 10,
"11"
=> 11,
"12"
=> 12
);
%Days
= (
"1"
=> 1,
"2"
=> 2,
"3"
=> 3,
"4"
=> 4,
"5"
=> 5,
"6"
=> 6,
"7"
=> 7,
"8"
=> 8,
"9"
=> 9,
"10"
=> 10,
"11"
=> 11,
"12"
=> 12,
"13"
=> 13,
"14"
=> 14,
"15"
=> 15,
"16"
=> 16,
"17"
=> 17,
"18"
=> 18,
"19"
=> 19,
"20"
=> 20,
"21"
=> 21,
"22"
=> 22,
"23"
=> 23,
"24"
=> 24,
"25"
=> 25,
"26"
=> 26,
"27"
=> 27,
"28"
=> 28,
"29"
=> 29,
"30"
=> 30,
"31"
=> 31,
"1st"
=> 1,
"2nd"
=> 2,
"3rd"
=> 3,
"4th"
=> 4,
"5th"
=> 5,
"6th"
=> 6,
"7th"
=> 7,
"8th"
=> 8,
"9th"
=> 9,
"10th"
=> 10,
"11th"
=> 11,
"12th"
=> 12,
"13th"
=> 13,
"14th"
=> 14,
"15th"
=> 15,
"16th"
=> 16,
"17th"
=> 17,
"18th"
=> 18,
"19th"
=> 19,
"20th"
=> 20,
"21st"
=> 21,
"22nd"
=> 22,
"23rd"
=> 23,
"24th"
=> 24,
"25th"
=> 25,
"26th"
=> 26,
"27th"
=> 27,
"28th"
=> 28,
"29th"
=> 29,
"30th"
=> 30,
"31st"
=> 31,
'first'
=> -1,
'second'
=> -2,
'third'
=> -3,
'fourth'
=> -4,
'fifth'
=> -5,
'sixth'
=> -6,
'seventh'
=> -7,
'eighth'
=> -8,
'ninth'
=> -9,
'tenth'
=> -10,
'eleventh'
=> -11,
'twelfth'
=> -12,
'thirteenth'
=> -13,
'fourteenth'
=> -14,
'fifteenth'
=> -15,
'sixteenth'
=> -16,
'seventeenth'
=> -17,
'eighteenth'
=> -18,
'nineteenth'
=> -19,
'twentieth'
=> -20,
'twenty-first'
=> -21,
'twenty-second'
=> -22,
'twenty-third'
=> -23,
'twenty-fourth'
=> -24,
'twenty-fifth'
=> -25,
'twenty-sixth'
=> -26,
'twenty-seventh'
=> -27,
'twenty-eighth'
=> -28,
'twenty-ninth'
=> -29,
'thirtieth'
=> -30,
'thirty-first'
=> -31,
'one'
=> -1,
'two'
=> -2,
'three'
=> -3,
'four'
=> -4,
'five'
=> -5,
'six'
=> -6,
'seven'
=> -7,
'eight'
=> -8,
'nine'
=> -9,
'ten'
=> -10,
'eleven'
=> -11,
'twelve'
=> -12,
'thirteen'
=> -13,
'fourteen'
=> -14,
'fifteen'
=> -15,
'sixteen'
=> -16,
'seventeen'
=> -17,
'eighteen'
=> -18,
'nineteen'
=> -19,
'twenty'
=> -20,
'twenty-one'
=> -21,
'twenty-two'
=> -22,
'twenty-three'
=> -23,
'twenty-four'
=> -24,
'twenty-five'
=> -25,
'twenty-six'
=> -26,
'twenty-seven'
=> -27,
'twenty-eight'
=> -28,
'twenty-nine'
=> -29,
'thirty'
=> -30,
'thirty-one'
=> -31,
);
my
$date_manip_installed_flag
=
keys
%date_manip_installed_languages
;
my
$date_language_installed_flag
=
keys
%date_language_installed_languages
;
my
$flip
=
$date_manip_installed_flag
|| (!
$date_language_installed_flag
);
$last_language_edit_flags
{language} =
"English"
;
$last_language_edit_flags
{month_period} = 0;;
$last_language_edit_flags
{dsuf_period} = 0;
$last_language_edit_flags
{dow_period} = 0;;
foreach
(
keys
%Months
) {
next
if
(
$Months
{
$_
} > 0 );
if
(
$flip
) {
$Months
{
$_
} =
abs
(
$Months
{
$_
});
}
else
{
delete
$Months
{
$_
};
}
}
foreach
(
keys
%Days
) {
next
if
(
$Days
{
$_
} > 0 );
if
(
$flip
) {
$Days
{
$_
} =
abs
(
$Days
{
$_
});
}
else
{
delete
$Days
{
$_
};
}
}
}
my
@days_in_months
= ( 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
my
$prev_array_lang
=
"English"
;
my
@gMoY
=
qw (
January February March April May June
July August September October November December );
my
@gMoYs
=
map
{
uc
(
substr
(
$_
,0,3)) }
@gMoY
;
my
@gDsuf
=
sort
{
my
(
$x
,
$y
) = (
$a
,
$b
);
$x
=~s/\D+$//;
$y
=~s/\D+$//;
$x
<=>
$y
}
grep
(/^\d+\D+$/,
keys
%Days
,
"0th"
);
my
@gDoW
=
qw( Sunday Monday Tuesday Wednesday Thursday Friday Saturday )
;
my
@gDoWs
=
map
{
uc
(
substr
(
$_
,0,3)) }
@gDoW
;
sub
_date_language_installed
{
return
(
scalar
(
keys
%date_language_installed_languages
) );
}
sub
_date_manip_installed
{
return
(
scalar
(
keys
%date_manip_installed_languages
) );
}
sub
get_languages
{
DBUG_ENTER_FUNC (
@_
);
my
%languages
;
foreach
my
$k1
(
keys
%date_language_installed_languages
) {
my
$lang
=
$date_language_installed_languages
{
$k1
}->{Language};
$languages
{
$lang
} = 1;
}
foreach
my
$k1
(
keys
%date_manip_installed_languages
) {
my
$lang
=
$date_manip_installed_languages
{
$k1
}->{Language};
my
$k2
= (
$k1
eq
lc
(
$lang
)) ?
$lang
:
$k1
;
$languages
{
$k2
} = 1;
}
if
(
scalar
(
keys
%languages
) == 0 ) {
$languages
{English} = 1;
}
DBUG_RETURN (
sort
keys
%languages
);
}
sub
_warn_msg
{
DBUG_ENTER_FUNC (
@_
);
my
$ok
=
shift
;
my
$msg
=
shift
;
if
(
$ok
) {
warn
"==> ${msg}\n"
;
}
DBUG_VOID_RETURN ();
}
sub
_swap_lang_common
{
DBUG_ENTER_FUNC (
@_
);
my
$lang_ref
=
shift
;
my
$warn_ok
=
shift
;
my
$allow_wide
=
shift
|| 0;
my
$base
=
"Date::Language"
;
my
$lang
=
$lang_ref
->{Language};
my
$module
=
$lang_ref
->{Module};
my
%issues
;
{
local
$SIG
{__DIE__} =
""
;
my
$sts
=
eval
"require ${module}"
;
unless
(
$sts
) {
_warn_msg (
$warn_ok
,
"${base} doesn't recognize '${lang}' as valid!"
);
return
DBUG_RETURN (
undef
,
undef
,
undef
,
undef
,
undef
, \
%issues
);
}
}
my
@lMoY
=
eval
"\@${module}::MoY"
;
my
@lMoYs
=
eval
"\@${module}::MoYs"
;
my
@lDsuf
=
eval
"\@${module}::Dsuf"
;
my
@lDoW
=
eval
"\@${module}::DoW"
;
my
@lDoWs
=
eval
"\@${module}::DoWs"
;
if
(
$#lMoY
== -1 &&
$#lMoYs
== -1 &&
$#lDsuf
== -1 &&
$#lDoW
== -1 &&
$#lDoWs
== -1 ) {
_warn_msg (
$warn_ok
,
"${base} doesn't recognize '${lang}' as valid due to case!"
);
return
DBUG_RETURN (
undef
,
undef
,
undef
,
undef
,
undef
, \
%issues
);
}
my
$num
=
@lDsuf
;
if
(
$num
> 29 ) {
my
$fix
=
$num
% 10;
foreach
(
$num
..31 ) {
my
$idx
=
$_
-
$num
+ 20 +
$fix
;
$lDsuf
[
$_
] =
$lDsuf
[
$idx
];
DBUG_PRINT (
"FIX"
,
"lDsuf[%d] = lDsuf[%d] = %s (%s)"
,
$_
,
$idx
,
$lDsuf
[
$_
],
$lang
);
}
}
my
$wide_flag
= 0;
foreach
(
@lMoY
,
@lMoYs
,
@lDsuf
,
@lDoW
,
@lDoWs
) {
my
$wide
= (
$_
=~ m/[^\x00-\xff]/ ) || 0;
if
(
$wide
) {
$wide_flag
= 1;
}
else
{
utf8::encode (
$_
);
utf8::decode (
$_
);
if
(
$_
=~ m/[^\x00-\xff]/ ||
uc
(
$_
) =~ m/[^\x00-\xff]/ ||
lc
(
$_
) =~ m/[^\x00-\xff]/ ) {
$wide_flag
= -1;
}
}
}
$lang_ref
->{Wide} =
$wide_flag
;
if
(
$wide_flag
&& !
$allow_wide
) {
_warn_msg (
$warn_ok
,
"'${lang}' uses Wide Chars. It's not currently enabled!"
);
return
DBUG_RETURN (
undef
,
undef
,
undef
,
undef
,
undef
, \
%issues
);
}
foreach
( 0..31 ) {
last
unless
(
defined
$lDsuf
[
$_
] );
$lDsuf
[
$_
] =
$_
.
$lDsuf
[
$_
];
$issues
{dsuf_period} = 1
if
(
$lDsuf
[
$_
] =~ m/[.]/ );
}
foreach
(
@lMoY
,
@lMoYs
) {
$issues
{month_period} = 1
if
(
$_
=~ m/[.]/ );
}
foreach
(
@lDoW
,
@lDoWs
) {
$issues
{dow_period} = 1
if
(
$_
=~ m/[.]/ );
}
DBUG_RETURN ( \
@lMoY
, \
@lMoYs
, \
@lDsuf
, \
@lDoW
, \
@lDoWs
, \
%issues
);
}
sub
_swap_manip_language_common
{
DBUG_ENTER_FUNC (
@_
);
my
$lang_ref
=
shift
;
my
$warn_ok
=
shift
;
my
$allow_wide
=
shift
|| 0;
my
$base
=
"Date::Manip"
;
my
$lang
=
$lang_ref
->{Language};
my
$module
=
$lang_ref
->{Module};
{
local
$SIG
{__DIE__} =
""
;
my
$sts
=
eval
"require ${module}"
;
unless
(
$sts
) {
_warn_msg (
$warn_ok
,
"${base} doesn't recognize '${lang}' as valid!"
);
return
( DBUG_RETURN (
undef
,
undef
,
undef
,
undef
,
undef
,
undef
,
undef
,
undef
) );
}
}
$lang_ref
->{Language} =
$lang
=
eval
"\$${module}::LangName"
;
my
$langData
=
eval
"\$${module}::Language"
;
my
(
%months
,
%days
,
%issues
);
my
(
@MoY
,
@MoYs
,
@Dsuf
,
@DoW
,
@DoWs
);
my
$wide
= 0;
my
$has_period
= 0;
foreach
my
$month_idx
(1..12) {
foreach
my
$name
( @{
$langData
->{month_name}->[
$month_idx
-1]} ) {
my
(
$w
,
$k
,
$pi
,
$pe
,
$alt
) = _fix_key (
$name
);
$wide
= 1
if
(
$w
);
next
if
(
$pe
&&
exists
$months
{
$alt
} &&
$months
{
$alt
} ==
$month_idx
);
$has_period
= 1
if
(
$pi
||
$pe
);
$months
{
$k
} =
$month_idx
;
}
foreach
my
$abb
( @{
$langData
->{month_abb}->[
$month_idx
-1]} ) {
my
(
$w
,
$k
,
$pi
,
$pe
,
$alt
) = _fix_key (
$abb
);
$wide
= 1
if
(
$w
);
next
if
(
$pe
&&
exists
$months
{
$alt
} &&
$months
{
$alt
} ==
$month_idx
);
$has_period
= 1
if
(
$pi
||
$pe
);
$months
{
$k
} =
$month_idx
;
}
my
$first_name
=
$langData
->{month_name}->[
$month_idx
-1]->[0];
my
$first_abb
=
$langData
->{month_abb}->[
$month_idx
-1]->[0];
push
(
@MoY
, (_fix_key (
$first_name
, 1))[1] );
push
(
@MoYs
, (_fix_key (
$first_abb
, 1))[1] );
}
$issues
{month_period} =
$has_period
;
$has_period
= 0;
foreach
my
$day_idx
(1..31) {
foreach
my
$day
( @{
$langData
->{nth}->[
$day_idx
-1]} ) {
my
(
$w
,
$k
,
$pi
,
$pe
,
$alt
) = _fix_key (
$day
);
$wide
= 1
if
(
$w
);
next
if
(
$pe
&&
exists
$days
{
$alt
} &&
$days
{
$alt
} ==
$day_idx
);
$has_period
= 1
if
(
$pi
||
$pe
);
$days
{
$k
} =
$day_idx
;
}
my
$first
=
$langData
->{nth}->[
$day_idx
-1]->[0];
push
(
@Dsuf
, (_fix_key (
$first
, 1))[1] );
}
$issues
{dsuf_period} =
$has_period
;
$has_period
= 0;
foreach
my
$wd_idx
(1..7) {
my
$wd
=
$langData
->{day_name}->[
$wd_idx
- 2]->[0];
my
(
$w
,
$k
,
$pi
,
$pe
,
$alt
) = _fix_key (
$wd
, 1 );
$wide
= 1
if
(
$w
);
push
(
@DoW
,
$k
);
$wd
=
$langData
->{day_abb}->[
$wd_idx
- 2]->[0];
(
$w
,
$k
,
$pi
,
$pe
,
$alt
) = _fix_key (
$wd
, 1 );
$wide
= 1
if
(
$w
);
push
(
@DoWs
,
$k
);
}
$issues
{dow_period} =
$has_period
;
$lang_ref
->{Wide} =
$wide
;
if
(
$wide
&& !
$allow_wide
) {
_warn_msg (
$warn_ok
,
"'${lang}' uses Wide Chars. It's not currently enabled!"
);
return
( DBUG_RETURN (
undef
,
undef
,
undef
,
undef
,
undef
,
undef
,
undef
,
undef
) );
}
DBUG_RETURN ( \
%months
, \
%days
, \
%issues
, \
@MoY
, \
@MoYs
, \
@Dsuf
, \
@DoW
, \
@DoWs
);
}
sub
_fix_key
{
my
$value
=
shift
;
my
$keep_case
=
shift
|| 0;
my
$wide
= (
$value
=~ m/[^\x00-\xff]/ ) ? 1 : 0;
unless
(
$wide
) {
utf8::encode (
$value
);
utf8::decode (
$value
);
if
(
$value
=~ m/[^\x00-\xff]/ ||
lc
(
$value
) =~ m/[^\x00-\xff]/ ||
uc
(
$value
) =~ m/[^\x00-\xff]/ ) {
$wide
= 1;
}
}
$value
=
lc
(
$value
)
unless
(
$keep_case
);
my
$alt
=
$value
;
my
(
$has_internal_period
,
$has_ending_period
) = (0, 0);
if
(
$value
=~ m/([.]?)[^.]*(.)$/ ) {
$has_internal_period
= 1
if
($1 eq
'.'
);
if
($2 eq
'.'
) {
$has_ending_period
= 1;
$alt
=~ s/[.]$//;
}
}
return
(
$wide
,
lc
$value
,
$has_internal_period
,
$has_ending_period
,
$alt
);
}
sub
_select_language
{
DBUG_ENTER_FUNC (
@_
);
my
$lang
=
shift
;
my
$warn_ok
=
shift
;
my
$allow_wide
=
shift
;
my
$k
=
lc
(
$lang
);
my
$manip_ref
=
$date_manip_installed_languages
{
$k
};
my
$lang_ref
=
$date_language_installed_languages
{
$k
};
if
(
$manip_ref
&& !
$lang_ref
) {
$k
=
lc
(
$manip_ref
->{Language});
$lang_ref
=
$date_language_installed_languages
{
$k
};
}
unless
(
$lang_ref
||
$manip_ref
) {
_warn_msg (
$warn_ok
,
"Language '$lang' does not exist! So can't swap to it!"
);
return
DBUG_RETURN (
undef
,
undef
);
}
unless
(
$allow_wide
) {
$manip_ref
=
undef
if
(
$manip_ref
&&
$manip_ref
->{Wide} );
$lang_ref
=
undef
if
(
$lang_ref
&&
$lang_ref
->{Wide} );
unless
(
$lang_ref
||
$manip_ref
) {
_warn_msg (
$warn_ok
,
"Language '$lang' uses Wide Chars. It's not currently enabled!"
);
return
DBUG_RETURN (
undef
,
undef
);
}
}
DBUG_RETURN (
$manip_ref
,
$lang_ref
);
}
sub
swap_language
{
DBUG_ENTER_FUNC (
@_
);
my
$lang
=
shift
;
my
$warn_ok
=
shift
;
my
$allow_wide
=
shift
|| 0;
if
( (!
defined
$lang
) ||
lc
(
$lang
) eq
lc
(
$last_language_edit_flags
{language}) ) {
return
DBUG_RETURN (
$last_language_edit_flags
{language} );
}
my
(
$manip_ref
,
$lang_ref
) = _select_language (
$lang
,
$warn_ok
,
$allow_wide
);
unless
(
$lang_ref
||
$manip_ref
) {
return
DBUG_RETURN (
$last_language_edit_flags
{language} );
}
my
(
$month_ref
,
$day_ref
,
$issue1_ref
);
if
(
$manip_ref
) {
my
$old
=
$manip_ref
->{Language};
(
$month_ref
,
$day_ref
,
$issue1_ref
) =
_swap_manip_language_common (
$manip_ref
,
$warn_ok
,
$allow_wide
);
$lang
=
$manip_ref
->{Language};
if
(
$old
ne
$lang
&& !
$lang_ref
) {
$lang_ref
=
$date_language_installed_languages
{
lc
(
$lang
)};
$lang_ref
=
undef
if
(
$lang_ref
&&
$lang_ref
->{Wide} && !
$allow_wide
);
}
}
my
(
$MoY_ref
,
$MoYs_ref
,
$Dsuf_ref
,
$issue2_ref
);
if
(
$lang_ref
) {
my
(
$unused_DoW_ref
,
$unused_DoWs_ref
);
(
$MoY_ref
,
$MoYs_ref
,
$Dsuf_ref
,
$unused_DoW_ref
,
$unused_DoWs_ref
,
$issue2_ref
) =
_swap_lang_common (
$lang_ref
,
$warn_ok
,
$allow_wide
);
$lang
=
$lang_ref
->{Language};
}
unless
(
$MoY_ref
||
$month_ref
) {
return
DBUG_RETURN (
$last_language_edit_flags
{language} );
}
DBUG_PRINT (
"SWAP"
,
"Swapping from '%s' to '%s'."
,
$last_language_edit_flags
{language},
$lang
);
foreach
my
$k
(
keys
%last_language_edit_flags
) {
$last_language_edit_flags
{
$k
} =
$issue1_ref
->{
$k
} ||
$issue2_ref
->{
$k
} || 0;
}
$last_language_edit_flags
{language} =
$lang
;
my
%empty
;
%Months
=
%Days
=
%empty
;
my
$cnt
;
foreach
$cnt
( 1..12 ) {
$Months
{
$cnt
} =
$cnt
;
}
foreach
my
$day
( 1..31 ) {
$Days
{
$day
} =
$day
;
}
foreach
my
$mon
(
keys
%{
$month_ref
} ) {
$Months
{
$mon
} =
$month_ref
->{
$mon
};
$Months
{
lc
(
uc
(
lc
(
$mon
)))} =
$Months
{
$mon
};
}
foreach
my
$day
(
keys
%{
$day_ref
} ) {
$Days
{
$day
} =
$day_ref
->{
$day
};
$Days
{
lc
(
uc
(
lc
(
$day
)))} =
$Days
{
$day
};
}
$cnt
= 1;
foreach
my
$mon
( @{
$MoY_ref
} ) {
$Months
{
lc
(
$mon
)} =
$cnt
;
$Months
{
lc
(
uc
(
lc
(
$mon
)))} =
$cnt
;
++
$cnt
;
}
$cnt
= 1;
foreach
my
$mon
( @{
$MoYs_ref
} ) {
$Months
{
lc
(
$mon
)} =
$cnt
;
$Months
{
lc
(
uc
(
lc
(
$mon
)))} =
$cnt
;
++
$cnt
;
}
foreach
my
$day
( 1..31 ) {
if
(
$Dsuf_ref
&&
defined
$Dsuf_ref
->[
$day
] ) {
my
$key
=
$Dsuf_ref
->[
$day
];
$Days
{
lc
(
$key
)} =
$day
;
$Days
{
lc
(
uc
(
lc
(
$key
)))} =
$day
;
}
}
DBUG_PRINT (
"LANGUAGE"
,
"%s\n%s\n%s"
,
join
(
", "
,
sort
{
$Months
{
$a
} <=>
$Months
{
$b
} ||
$a
cmp
$b
}
keys
%Months
),
join
(
", "
,
sort
{
my
(
$x
,
$y
) = (
$a
,
$b
);
$x
=~s/\D+//g;
$y
=~s/\D+//g;
$x
=0
if
(
$x
eq
""
);
$y
=0
if
(
$y
eq
""
); (
$x
<=>
$y
||
$a
cmp
$b
) }
keys
%Days
),
join
(
", "
,
%last_language_edit_flags
) );
DBUG_RETURN (
$lang
);
}
sub
lcx
{
my
$str
=
shift
;
unless
( utf8::is_utf8 (
$str
) ) {
utf8::encode (
$str
);
utf8::decode (
$str
);
}
return
(
lc
(
$str
));
}
sub
_tst
{
my
$s
=
shift
;
my
$nm
=
shift
;
my
$dm
=
shift
;
DBUG_PRINT (
"TST"
,
"Matched Pattern (%s) Sep: %s Name: %s Dom: %s"
,
join
(
","
,
@_
),
$s
,
$nm
,
$dm
);
return
(1);
}
sub
parse_date_old
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$date_format_options
=
shift
;
my
$use_date_language_module
=
shift
|| 0;
my
$allow_2_digit_years
=
shift
|| 0;
my
$name
=
"[^-\$\\s\\d.,|\\[\\]\\\\/{}()]"
;
my
$dom
=
"\\d{0,2}${name}*"
;
$name
=~ s/\\s//g
if
(
$last_language_edit_flags
{month_spaces} );
$name
=~ s/[.]//g
if
(
$last_language_edit_flags
{month_period} );
$name
=~ s/-//g
if
(
$last_language_edit_flags
{month_hyphin} );
$name
.=
'+'
;
$dom
=~ s/\\s//g
if
(
$last_language_edit_flags
{dsuf_spaces} );
$dom
=~ s/[.]//g
if
(
$last_language_edit_flags
{dsuf_period} );
$dom
=~ s/-//g
if
(
$last_language_edit_flags
{dsuf_hyphin} );
my
(
$year
,
$month
,
$day
);
my
(
$s1
,
$s2
) = (
""
,
""
);
my
$fmt
=
"n/a"
;
my
@seps
= (
"-"
,
"/"
,
"[.]"
,
","
,
"\\s+"
,
'\\\\'
,
":"
);
foreach
my
$sep
(
@seps
) {
if
(
$in_date
=~ m/(^|\D)(\d{4})(${sep})(\d{1,2})(${sep})(\d{1,2})(\D|$)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"YYYY${s1}MM${s2}DD"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{1,2})(${sep})(\d{1,2})(${sep})(\d{4})(\D|$)/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
(
$year
,
$month
,
$day
) = parse_8_digit_date (
sprintf
(
"%02d%02d%04d"
,
$month
,
$day
,
$year
),
$date_format_options
, 1 );
$fmt
=
"MM${s1}DD${s2}YYYY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{1,2})(${sep})(${name})[.]?(${sep})(\d{4})(\D|$)/ &&
exists
$Months
{lcx($4)} ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"DD${s1}Month${s2}YYYY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(${sep})(${name})[.]?(${sep})(\d{1,2})(\D|$)/ &&
exists
$Months
{lcx($4)} ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"YYYY${s1}Month${s2}DD"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${name})(${sep})(\d{1,2})(${sep})(\d{4})(\D|$)/ &&
exists
$Months
{lcx($2)} ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"Month${s1}DD${s2}YYYY"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${dom})(${sep})(${name})[.]?(${sep})(\d{4})(\D|$)/ &&
exists
$Months
{lcx($4)} &&
exists
$Days
{lcx($2)} ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"Day${s1}Month${s2}YYYY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(${sep})(${name})[.]?(${sep})(${dom})(\s|$)/ &&
exists
$Months
{lcx($4)} &&
exists
$Days
{lcx($6)} ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"YYYY${s1}Month${s2}Day"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${name})(${sep})(${dom})(${sep})(\d{4})(\D|$)/ &&
exists
$Months
{lcx($2)} &&
exists
$Days
{lcx($4)} ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$fmt
=
"Month${s1}Day${s2}YYYY"
;
}
last
if
(
defined
$year
);
}
if
(
defined
$year
) {
;
}
elsif
(
$in_date
=~ m/(${name})[.\s]\s*(${dom})[,\s]\s*(\d{4})(\D|$)/ &&
exists
$Months
{lcx($1)} ) {
(
$month
,
$day
,
$year
) = ( $1, $2, $3 );
$fmt
=
"Month Day, YYYY"
;
}
elsif
(
$in_date
=~ m/(${name})[.]?\s+(${dom})[,\s]\s*(\d{1,2}:\d{1,2}(:\d{1,2})?)\s+(\d{4})(\D|$)/ &&
exists
$Months
{lcx($1)} ) {
my
$time
;
(
$month
,
$day
,
$time
,
$year
) = ( $1, $2, $3, $5 );
$fmt
=
"Month Day HH:MM[:SS] YYYY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{8})(\D|$)/ ) {
(
$year
,
$month
,
$day
) = parse_8_digit_date ( $2,
$date_format_options
, 0 );
$fmt
=
"YYYYMMDD"
;
}
elsif
(
$allow_2_digit_years
) {
foreach
my
$sep
(
@seps
) {
next
if
(
$sep
eq
":"
);
if
(
$in_date
=~ m/(^|[^:\d])(\d{1,2})(${sep})(\d{1,2})(${sep})(\d{1,2})([^:\d]|$)/ ) {
(
$s1
,
$s2
) = ($3, $5);
my
$yymmdd
=
sprintf
(
"%02d%02d%02d"
, $2, $4, $6);
(
$year
,
$month
,
$day
) = parse_6_digit_date (
$yymmdd
,
$date_format_options
);
$fmt
=
"YY${s1}MM${s2}DD ???"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{1,2})(${sep})(${name})[.]?(${sep})(\d{1,2})([^:\d]|$)/ &&
exists
$Months
{lcx($4)} ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
my
$yymmdd
=
sprintf
(
"%02d%02d%02d"
,
$year
,
$Months
{lcx(
$month
)},
$day
);
my
@order
;
foreach
(
split
(/\s*,\s*/,
$date_format_options
) ) {
push
(
@order
,
$_
)
if
(
$_
!= 2 );
}
(
$year
,
$month
,
$day
) = parse_6_digit_date (
$yymmdd
,
join
(
","
,
@order
) );
$fmt
=
"DD${s1}Month${s2}YY or YY${s1}Month${s2}DD"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${name})(${sep})(\d{1,2})(${sep})(\d{1,2})([^:\d]|$)/ &&
exists
$Months
{lcx($2)} ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
$fmt
=
"Month${s1}DD${s2}YY"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${name})[.]?(${sep})(${dom})(${sep})(\d{1,2})([^:\d]|$)/ &&
_tst(
$sep
,
$name
,
$dom
, $2, $4, $6 ) &&
exists
$Months
{lcx($2)} &&
exists
$Days
{lcx($4)} ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
$fmt
=
"Month${s1}Day${s2}YY"
;
}
elsif
(
$in_date
=~ m/(^|\s)(${dom})(${sep})(${name})[.]?(${sep})(\d{1,2})([^:\d]|$)/ &&
_tst(
$sep
,
$name
,
$dom
, $2, $4, $6 ) &&
exists
$Months
{lcx($4)} &&
exists
$Days
{lcx($2)} ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
$fmt
=
"Day${s1}Month${s2}YY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{1,2})(${sep})(${name})[.]?(${sep})(${dom})(\s|$)/ &&
_tst(
$sep
,
$name
,
$dom
, $2, $4, $6 ) &&
exists
$Months
{lcx($4)} &&
exists
$Days
{lcx($6)} ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
$fmt
=
"YY${s1}Month${s2}Day"
;
}
last
if
(
defined
$year
);
}
if
(
defined
$year
) {
;
}
elsif
(
$in_date
=~ m/(${name})[.\s]\s*(${dom})[,\s]\s*(\d{2})(\D|$)/ &&
_tst(
"\\s"
,
$name
,
$dom
, $1, $2, $3 ) &&
exists
$Months
{lcx($1)} ) {
(
$month
,
$day
) = ( $1, $2 );
$year
= make_it_a_4_digit_year ( $3 );
$fmt
=
"Month Day, YY"
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{6})(\D|$)/ ) {
(
$year
,
$month
,
$day
) = parse_6_digit_date ( $2,
$date_format_options
);
$fmt
=
"YYMMDD"
;
}
}
if
(
$use_date_language_module
&& !
defined
$year
) {
unless
( _date_language_installed () ) {
DBUG_PRINT (
"INFO"
,
"Using Date::Language::str2time was requested, but it's not installed!"
);
}
else
{
DBUG_PRINT (
"INFO"
,
"Using Date::Language::str2time to attempt the parse!"
);
eval
{
my
$dl
= Date::Language->new (
$last_language_edit_flags
{language} );
my
$t
=
$dl
->str2time (
$in_date
);
if
(
defined
$t
) {
(
$year
,
$month
,
$day
) = (
localtime
(
$t
))[5,4,3];
$year
+= 1900;
$month
+= 1;
}
};
}
}
if
( !
defined
$year
) {
DBUG_PRINT (
"ERROR"
,
"No such date format is supported: %s"
,
$in_date
);
}
else
{
DBUG_PRINT (
"FORMAT"
,
"%s ==> %s ==> (Y:%s, M:%s, D:%s, Sep:%s)"
,
$fmt
,
$in_date
,
$year
,
$month
,
$day
,
$s1
);
if
(
$s1
ne
$s2
) {
unless
(
$s1
=~ m/^\s*$/ &&
$s2
=~ m/^\s*$/ ) {
die
(
"BUG: Separators are different ($s1 vs $s2)\n"
);
}
}
$day
= $1
if
(
$day
=~ m/^\s*(.*)\s*$/ );
return
DBUG_RETURN ( _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
) );
}
DBUG_RETURN (
undef
);
}
sub
parse_date
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$date_format_options
=
shift
;
my
$use_date_language_module
=
shift
|| 0;
my
$allow_2_digit_years
=
shift
|| 0;
$in_date
= lcx (
$in_date
);
my
(
$month
,
$month_digits
) = _find_month_in_string (
$in_date
);
my
(
$dom
,
$dom_digits
) = _find_day_of_month_in_string (
$in_date
,
$month_digits
,
$month_digits
?
undef
:
$month
);
my
$out_str
;
if
(
$month_digits
&&
$dom_digits
) {
$out_str
= _month_num_day_num (
$in_date
,
$month
,
$dom
,
$allow_2_digit_years
,
$date_format_options
);
}
elsif
(
$month_digits
) {
$out_str
= _month_num_day_str (
$in_date
,
$month
,
$dom
,
$allow_2_digit_years
);
}
elsif
(
$dom_digits
) {
$out_str
= _month_str_day_num (
$in_date
,
$month
,
$dom
,
$allow_2_digit_years
,
$date_format_options
);
}
else
{
$out_str
= _month_str_day_str (
$in_date
,
$month
,
$dom
,
$allow_2_digit_years
);
}
if
(
$use_date_language_module
&& (!
$out_str
) &&
_date_language_installed () ) {
DBUG_PRINT (
"INFO"
,
"Using Date::Language::str2time to attempt parsing!"
);
eval
{
my
$dl
= Date::Language->new (
$last_language_edit_flags
{language} );
my
$t
=
$dl
->str2time (
$in_date
);
if
(
defined
$t
) {
my
(
$year
,
$month
,
$day
) = (
localtime
(
$t
))[5,4,3];
$year
+= 1900;
$month
+= 1;
$out_str
= _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
);
}
};
}
DBUG_RETURN (
$out_str
);
}
sub
_month_str_day_str
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$month_str
=
shift
;
my
$dom_str
=
shift
;
my
$allow_2_digit_years
=
shift
;
my
(
$year
,
$s1
,
$month
,
$s2
,
$day
);
if
(
$in_date
=~ m/(^|\D)(${month_str})[.]?(.*?\D)(${dom_str})(.*?\D)(\d{4})($|\D)/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_str})(.+?)(${month_str})[.]?(.*?\D)(\d{4})($|\D)/ ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(\D.*?)(${month_str})[.]?(.*?\D)(${dom_str})($|\D)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
}
if
(
$allow_2_digit_years
&& !
defined
$year
) {
if
(
$in_date
=~ m/(^|\D)(${month_str})[.]?(.*?\D)(${dom_str})(.*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_str})(.+?)(${month_str})[.]?(.*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d].*?)(${month_str})[.]?(.*?\D)(${dom_str})($|\D)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
}
$year
= make_it_a_4_digit_year (
$year
)
if
(
defined
$year
);
}
if
(
defined
$year
) {
return
DBUG_RETURN ( _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
) );
}
DBUG_RETURN (
undef
);
}
sub
_tst_4_YY
{
my
$sep
=
shift
;
my
$res
= (
$sep
=~ m/\s\d{1,2}\s/ ) ? 0 : 1;
return
(
$res
);
}
sub
_month_str_day_num
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$month_str
=
shift
;
my
$dom_num
=
shift
;
my
$allow_2_digit_years
=
shift
;
my
$date_format_options
=
shift
;
my
(
$year
,
$s1
,
$month
,
$s2
,
$day
);
if
(
$in_date
=~ m/(^|\D)(${month_str})[.]?([^\d]*?\D)(${dom_num})(\D)(\d{4})($|\D)/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
DBUG_PRINT (
"AMERICAN-1"
,
"${month}/${day}/${year} -- ($s1) ($s2)"
);
}
elsif
(
$in_date
=~ m/(^|\D)(${month_str})[.]?([^\d]*?\D)(${dom_num})(\D.*?\D)(\d{4})($|\D)/ &&
_tst_4_YY ( $5 ) ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
DBUG_PRINT (
"AMERICAN-2"
,
"${month}/${day}/${year} -- ($s1) ($s2)"
);
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_num})(\D*?)(${month_str})[.]?(.*?\D)(\d{4})($|\D)/ &&
_tst_4_YY ( $5 ) ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
DBUG_PRINT (
"EUROPEAN"
,
"${day}/${month}/${year} -- ($s1) ($s2)"
);
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(\D*?)(${month_str})[.]?(.*?\D)(${dom_num})($|\D)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
DBUG_PRINT (
"ISO"
,
"${year}/${month}/${day} -- ($s1) ($s2)"
);
}
if
(
$allow_2_digit_years
&& !
defined
$year
) {
if
(
$in_date
=~ m/(^|\D)(${month_str})[.]?(.*?[^:\d])(${dom_num})([^:\d])(\d{2})($|[^:\d])/ ||
$in_date
=~ m/(^|\D)(${month_str})[.]?(.*?[^:\d])(${dom_num})([^:\d].*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_num})([^:\d].*?)(${month_str})[.]?(.*?[^:\d])(${dom_num})($|[^:\d])/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
my
$yymmdd
=
sprintf
(
"%02d%02d%02d"
,
$year
,
$Months
{lcx(
$month
)},
$day
);
my
@order
;
foreach
(
split
(/\s*,\s*/,
$date_format_options
) ) {
push
(
@order
,
$_
)
if
(
$_
!= 2 );
}
(
$year
,
$month
,
$day
) = parse_6_digit_date (
$yymmdd
,
join
(
","
,
@order
) );
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_num})([^:\d].*?)(${month_str})[.]?(.*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
}
elsif
(
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d].*?)(${month_str})[.]?(.*?[^:\d])(${dom_num})($|[^:\d])/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
$year
= make_it_a_4_digit_year (
$year
);
}
}
if
(
defined
$year
) {
return
DBUG_RETURN ( _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
) );
}
DBUG_RETURN (
undef
);
}
sub
_month_num_day_str
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$month_num
=
shift
;
my
$dom_str
=
shift
;
my
$allow_2_digit_years
=
shift
;
my
(
$year
,
$s1
,
$month
,
$s2
,
$day
);
if
(
$in_date
=~ m/(^|[^:\d])(${month_num})(\D)(${dom_str})(.*?\D)(\d{4})($|\D)/ ||
$in_date
=~ m/(^|[^:\d])(${month_num})(\D.*?\D)(${dom_str})(.*?\D)(\d{4})($|\D)/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_str})(.*?\D)(${month_num})(\D)(\d{4})($|\D)/ ||
$in_date
=~ m/(^|\D)(${dom_str})(.*?\D)(${month_num})(\D.*?\D)(\d{4})($|\D)/ ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(\D)(${month_num})(\D)(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|\D)(\d{4})(\D)(${month_num})(\D.*?\D)(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|\D)(\d{4})(\D.*?\D)(${month_num})(\D)(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|\D)(\d{4})(\D.*?\D)(${month_num})(\D.*?\D)(${dom_str})($|\D)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
}
if
(
$allow_2_digit_years
&& !
defined
$year
) {
if
(
$in_date
=~ m/(^|\D)(${month_num})([^:\d])(${dom_str})(.*?[^:\d])(\d{2})($|[^:\d])/ ||
$in_date
=~ m/(^|\D)(${month_num})([^:\d].*?[^:\d])(${dom_str})(.*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$month
,
$s1
,
$day
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|\D)(${dom_str})(.*?[^:\d])(${month_num})([^:\d])(\d{2})($|[^:\d])/ ||
$in_date
=~ m/(^|\D)(${dom_str})(.*?[^:\d])(${month_num})([^:\d].*?[^:\d])(\d{2})($|[^:\d])/ ) {
(
$day
,
$s1
,
$month
,
$s2
,
$year
) = ( $2, $3, $4, $5, $6 );
}
elsif
(
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d])(${month_num})([^:\d])(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d])(${month_num})([^:\d].*?[^:\d])(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d].*?[^:\d])(${month_num})([^:\d])(${dom_str})($|\D)/ ||
$in_date
=~ m/(^|[^:\d])(\d{2})([^:\d].*?[^:\d])(${month_num})([^:\d].*?[^:\d])(${dom_str})($|\D)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
}
$year
= make_it_a_4_digit_year (
$year
)
if
(
defined
$year
);
}
if
(
defined
$year
) {
return
DBUG_RETURN ( _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
) );
}
DBUG_RETURN (
undef
);
}
sub
_month_num_day_num
{
DBUG_ENTER_FUNC (
@_
);
my
$in_date
=
shift
;
my
$month_num
=
shift
;
my
$dom_num
=
shift
;
my
$allow_2_digit_years
=
shift
;
my
$date_format_options
=
shift
;
my
(
$year
,
$s1
,
$month
,
$s2
,
$day
);
if
(
$in_date
=~ m/(^|\D)(\d{8})($|\D)/ ) {
(
$year
,
$month
,
$day
) = parse_8_digit_date ( $2,
$date_format_options
, 0 );
$s1
=
$s2
=
""
;
}
elsif
(
$in_date
=~ m/(^|\D)(\d{1,2})(\D+)(\d{1,2})(\D+)(\d{4})(\D|$)/ ) {
(
$s1
,
$s2
) = ( $3, $5 );
my
$date
=
sprintf
(
"%02d%02d%04d"
, $2, $4, $6);
(
$year
,
$month
,
$day
) = parse_8_digit_date (
$date
,
$date_format_options
, 1 );
}
elsif
(
$in_date
=~ m/(^|\D)(\d{4})(\D+)(${month_num})(\D+)(${dom_num})(\D|$)/ ) {
(
$year
,
$s1
,
$month
,
$s2
,
$day
) = ( $2, $3, $4, $5, $6 );
}
if
(
$allow_2_digit_years
&& !
defined
$year
) {
if
(
$in_date
=~ m/(^|\D)(\d{6})($|\D)/ ) {
(
$year
,
$month
,
$day
) = parse_6_digit_date ( $2,
$date_format_options
);
$s1
=
$s2
=
""
;
}
elsif
(
$in_date
=~ m/(^|[^:\d])(\d{1,2})([^:\d]+)(\d{1,2})([^:\d]+)(\d{1,2})([^:\d]|$)/ ) {
(
$s1
,
$s2
) = ( $3, $5 );
my
$date
=
sprintf
(
"%02d%02d%02d"
, $2, $4, $6);
(
$year
,
$month
,
$day
) = parse_6_digit_date (
$date
,
$date_format_options
);
}
}
if
(
defined
$year
) {
return
DBUG_RETURN ( _check_if_good_date (
$in_date
,
$year
,
$month
,
$day
) );
}
DBUG_RETURN (
undef
);
}
sub
_check_if_good_date
{
DBUG_ENTER_FUNC (
@_
);
my
$in_str
=
shift
;
my
$year
=
shift
;
my
$month
=
shift
;
my
$day
=
shift
;
$month
=~ s/^0+//;
$day
=~ s/^0+//;
$month
=
$Months
{lcx(
$month
)};
$day
=
$Days
{lcx(
$day
)};
my
$err_msg
;
if
(
defined
$month
&&
defined
$day
) {
;
}
elsif
(
defined
$month
) {
$err_msg
=
"Just the day of month is bad."
;
}
elsif
(
defined
$day
) {
$err_msg
=
"Just the month is bad."
;
}
else
{
$err_msg
=
"Both the month and day are bad."
;
}
unless
(
$err_msg
) {
if
( 1 <=
$day
&&
$day
<=
$days_in_months
[
$month
] ) {
;
}
elsif
(
$month
== 2 &&
$day
== 29 ) {
my
$leap
= (
$year
% 4 == 0) && (
$year
% 100 != 0 ||
$year
% 400 == 0);
$year
=
undef
unless
(
$leap
);
}
else
{
$year
=
undef
;
}
unless
(
defined
$year
) {
$err_msg
=
"The day of month is out of range."
;
}
}
if
(
$err_msg
) {
DBUG_PRINT (
"ERROR"
,
"'%s' was an invalid date!\n%s"
,
$in_str
,
$err_msg
);
DBUG_PRINT (
"BAD"
,
"%s-%s-%s"
,
$year
,
$month
,
$day
);
return
( DBUG_RETURN (
undef
) );
}
DBUG_RETURN (
sprintf
(
"%04d-%02d-%02d"
,
$year
,
$month
,
$day
) );
}
sub
_find_month_in_string
{
DBUG_ENTER_FUNC (
@_
);
my
$date_str
=
shift
;
my
$month
;
my
$digits
= 0;
my
@lst
=
sort
{
length
(
$b
) <=>
length
(
$a
) ||
$a
cmp
$b
}
keys
%Months
;
foreach
my
$m
(
@lst
) {
next
if
(
$m
=~ m/^\d+$/ );
my
$flag1
= (
$last_language_edit_flags
{month_period} &&
$m
=~ s/[.]/\\./g );
if
(
$date_str
=~ m/(${m})/ ) {
$month
= $1;
$month
=~ s/[.]/\\./g
if
(
$flag1
);
last
;
}
}
unless
(
$month
) {
$month
=
"[1-9]|0[1-9]|1[0-2]"
;
$digits
= 1;
}
DBUG_RETURN (
$month
,
$digits
);
}
sub
_find_day_of_month_in_string
{
DBUG_ENTER_FUNC (
@_
);
my
$date_str
=
shift
;
my
$skip_period
=
shift
;
my
$month_str
=
shift
;
my
$day
;
my
$digits
= 0;
my
@lst
=
sort
{
length
(
$b
) <=>
length
(
$a
) ||
$a
cmp
$b
}
keys
%Days
;
my
$all_digits
=
$skip_period
?
"^\\d+[.]?\$"
:
"^\\d+\$"
;
foreach
my
$dom
(
@lst
) {
next
if
(
$dom
=~ m/${all_digits}/ );
my
$flag1
= (
$last_language_edit_flags
{dsuf_period} &&
$dom
=~ s/[.]/\\./g );
if
(
$month_str
) {
$month_str
=~ s/[.]/\\./g;
if
(
$date_str
=~ m/${month_str}.*(${dom})/ ||
$date_str
=~ m/(${dom}).*${month_str}/ ) {
$day
= $1;
$day
=~ s/[.]/\\./g
if
(
$flag1
);
last
;
}
}
elsif
(
$date_str
=~ m/(${dom})/ ) {
$day
= $1;
$day
=~ s/[.]/\\./g
if
(
$flag1
);
last
;
}
}
unless
(
$day
) {
$day
=
"[1-9]|0[1-9]|[12][0-9]|3[01]"
;
$digits
= 1;
}
DBUG_RETURN (
$day
,
$digits
);
}
sub
adjust_future_cutoff
{
DBUG_ENTER_FUNC (
@_
);
my
$years
=
shift
;
if
(
defined
$years
&&
$years
=~ m/^\d+$/ ) {
$global_cutoff_date
=
shift
;
}
DBUG_VOID_RETURN ();
}
sub
make_it_a_4_digit_year
{
DBUG_ENTER_FUNC (
@_
);
my
$year
=
shift
|| 0;
$year
+= 2000;
my
$this_yr
= (
localtime
(
time
()))[5];
$this_yr
+= 1900;
if
(
$this_yr
<
$year
&& (
$year
-
$this_yr
) >=
$global_cutoff_date
) {
$year
-= 100;
}
DBUG_RETURN (
$year
);
}
sub
parse_8_digit_date
{
DBUG_ENTER_FUNC (
@_
);
my
$date_str
=
shift
;
my
$order
=
shift
;
my
$skip_iso
=
shift
|| 0;
my
@order
=
split
(/\s*,\s*/,
$order
);
my
@lbls
= (
""
,
"YYYYMMDD - ISO"
,
"MMDDYYYY - American"
,
"DDMMYYYY - European"
);
my
(
$year
,
$month
,
$day
);
foreach
my
$id
(
@order
) {
next
unless
(
defined
$id
&&
$id
=~ m/^[123]$/ );
my
(
$y
,
$m
,
$d
) = ( 0, 0, 0 );
if
(
$id
== 1 && (!
$skip_iso
) &&
$date_str
=~ m/^(\d{4})(\d{2})(\d{2})$/ ) {
(
$y
,
$m
,
$d
) = ( $1, $2, $3 );
}
if
(
$id
== 2 &&
$date_str
=~ m/^(\d{2})(\d{2})(\d{4})$/ ) {
(
$m
,
$d
,
$y
) = ( $1, $2, $3 );
}
if
(
$id
== 3 &&
$date_str
=~ m/^(\d{2})(\d{2})(\d{4})$/ ) {
(
$d
,
$m
,
$y
) = ( $1, $2, $3 );
}
if
( 1 <=
$m
&&
$m
<= 12 && 1 <=
$d
&&
$d
<= 31 ) {
DBUG_PRINT (
"INFO"
,
"Validating if using %s format."
,
$lbls
[
$id
]);
my
$max
=
$days_in_months
[
$m
];
if
(
$m
== 2 ) {
my
$leap
= (
$y
% 4 == 0) && (
$y
% 100 != 0 ||
$y
% 400 == 0);
++
$max
if
(
$leap
);
}
if
(
$d
<=
$max
) {
(
$year
,
$month
,
$day
) = (
$y
,
$m
,
$d
);
last
;
}
}
}
DBUG_RETURN (
$year
,
$month
,
$day
);
}
sub
parse_6_digit_date
{
DBUG_ENTER_FUNC (
@_
);
my
$date_str
=
shift
;
my
$order
=
shift
;
my
@order
=
split
(/\s*,\s*/,
$order
);
my
@lbls
= (
""
,
"YYMMDD - ISO"
,
"MMDDYY - American"
,
"DDMMYY - European"
);
my
(
$year
,
$month
,
$day
);
if
(
$date_str
=~ m/^(\d{2})(\d{2})(\d{2})$/ ) {
my
@part
= ( $1, $2, $3 );
foreach
my
$id
(
@order
) {
next
unless
(
defined
$id
&&
$id
=~ m/^[123]$/ );
my
(
$y
,
$m
,
$d
) = ( 0, 0, 0 );
if
(
$id
== 1 &&
1 <=
$part
[1] &&
$part
[1] <= 12 &&
1 <=
$part
[2] &&
$part
[2] <= 31 ) {
(
$m
,
$d
,
$y
) = (
$part
[1],
$part
[2],
$part
[0] );
}
if
(
$id
== 2 &&
1 <=
$part
[0] &&
$part
[0] <= 12 &&
1 <=
$part
[1] &&
$part
[1] <= 31 ) {
(
$m
,
$d
,
$y
) = (
$part
[0],
$part
[1],
$part
[2] );
}
if
(
$id
== 3 &&
1 <=
$part
[1] &&
$part
[1] <= 12 &&
1 <=
$part
[0] &&
$part
[0] <= 31 ) {
(
$m
,
$d
,
$y
) = (
$part
[1],
$part
[0],
$part
[2] );
}
if
(
$m
> 0 ) {
DBUG_PRINT (
"INFO"
,
"Validating if using %s format."
,
$lbls
[
$id
]);
$y
= make_it_a_4_digit_year (
$y
);
my
$max
=
$days_in_months
[
$m
];
if
(
$m
== 2 ) {
my
$leap
= (
$y
% 4 == 0) && (
$y
% 100 != 0 ||
$y
% 400 == 0);
++
$max
if
(
$leap
);
}
if
(
$d
<=
$max
) {
(
$year
,
$month
,
$day
) = (
$y
,
$m
,
$d
);
last
;
}
}
}
}
DBUG_RETURN (
$year
,
$month
,
$day
);
}
sub
init_special_date_arrays
{
DBUG_ENTER_FUNC (
@_
);
my
$lang
=
shift
;
my
$mode
=
shift
|| 0;
my
$warn_ok
=
shift
|| 0;
my
$allow_wide
=
shift
|| 0;
my
@months
= (
"01"
,
"02"
,
"03"
,
"04"
,
"05"
,
"06"
,
"07"
,
"08"
,
"09"
,
"10"
,
"11"
,
"12"
);
my
@week_days
= (
"1"
,
"2"
,
"3"
,
"4"
,
"5"
,
"6"
,
"7"
);
my
$numbers
= (
$mode
!= 1 &&
$mode
!= 2 );
my
(
$lang_ref
,
$manip_ref
);
if
(
defined
$lang
) {
(
$manip_ref
,
$lang_ref
) = _select_language (
$lang
,
$warn_ok
,
$allow_wide
);
unless
(
$lang_ref
||
$manip_ref
) {
$lang
=
undef
;
}
}
if
( (!
defined
$lang
) ||
lc
(
$lang
) eq
lc
(
$prev_array_lang
) ||
$numbers
) {
if
(
$mode
== 1 ) {
@months
=
@gMoYs
;
@week_days
=
@gDoWs
;
}
elsif
(
$mode
== 2 ) {
@months
=
@gMoY
;
@week_days
=
@gDoW
;
}
return
DBUG_RETURN ( \
@months
, \
@week_days
);
}
my
(
$MoY_ref
,
$MoYs_ref
,
$Dsuf_ref
,
$DoW_ref
,
$DoWs_ref
);
DBUG_PRINT (
"INFO"
,
"Manip: %s, Lang: %s"
,
$manip_ref
,
$lang_ref
);
if
(
$manip_ref
) {
my
(
$u1
,
$u2
,
$u3
);
(
$u1
,
$u2
,
$u3
,
$MoY_ref
,
$MoYs_ref
,
$Dsuf_ref
,
$DoW_ref
,
$DoWs_ref
) =
_swap_manip_language_common (
$manip_ref
,
$warn_ok
,
$allow_wide
);
$lang
=
$manip_ref
->{Language};
if
(
$u1
) {
$lang_ref
=
undef
;
}
else
{
$lang_ref
=
$date_language_installed_languages
{
lc
(
$lang
)};
}
}
if
(
$lang_ref
) {
(
$MoY_ref
,
$MoYs_ref
,
$Dsuf_ref
,
$DoW_ref
,
$DoWs_ref
) =
_swap_lang_common (
$lang_ref
,
$warn_ok
,
$allow_wide
);
$lang
=
$lang_ref
->{Language};
}
if
(
$MoY_ref
) {
$prev_array_lang
=
$lang
;
@gMoY
= @{
$MoY_ref
};
@gMoYs
=
map
{
uc
(
$_
) } @{
$MoYs_ref
};
@gDoW
= @{
$DoW_ref
};
@gDoWs
=
map
{
uc
(
$_
) } @{
$DoWs_ref
};
@gDsuf
= @{
$Dsuf_ref
};
DBUG_PRINT (
"LANGUAGE"
,
"%s\n%s\n%s\n%s\n%s"
,
join
(
", "
,
@gMoY
),
join
(
", "
,
@gMoYs
),
join
(
", "
,
@gDoW
),
join
(
", "
,
@gDoWs
),
join
(
", "
,
@gDsuf
)
);
}
if
(
$mode
== 1 ) {
@months
=
@gMoYs
;
@week_days
=
@gDoWs
;
}
elsif
(
$mode
== 2 ) {
@months
=
@gMoY
;
@week_days
=
@gDoW
;
}
DBUG_RETURN ( \
@months
, \
@week_days
);
}
1;