| File | /usr/share/perl5/Date/Manip.pm |
| Statements Executed | 105 |
| Total Time | 0.0514257 seconds |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0s | 0s | Date::Manip::BEGIN |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::DateCalc |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::DateManipVersion |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_Cmp |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_ConvTZ |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DayOfWeek |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DayOfYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DaySuffix |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DaysInMonth |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DaysInYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_DaysSince1BC |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_GetNext |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_GetPrev |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_Init |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_IsHoliday |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_IsWorkDay |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_LeapYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_NearestWorkDay |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_NextWorkDay |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_NthDayOfYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_PrevWorkDay |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_SecsSince1970 |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_SecsSince1970GMT |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_SetDateField |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_SetTime |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_TimeZone |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Date_WeekOfYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Delta_Format |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::EraseHolidays |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::Events_List |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::ParseDate |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::ParseDateDelta |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::ParseDateString |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::ParseRecur |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::UnixDate |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Char_8Bit |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_CheckFilePath |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_CheckTime |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_CleanFile |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_DateCalc_DateDate |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_DateCalc_DateDelta |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_DateCalc_DeltaDelta |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_DateCheck |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Easter |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_FixYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_InitFile |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_InitHash |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_InitLists |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_InitStrings |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Catalan |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Danish |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Dutch |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_English |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_French |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_German |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Italian |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Polish |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Portuguese |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Romanian |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Russian |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Spanish |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Swedish |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Init_Turkish |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Join |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_NthWeekOfYear |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_ParseTime |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Recur |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_RecurSetTime |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Recur_WoM |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Regexp |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_SetConfigVariable |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_Split |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_TimeCheck |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Date_UpdateHolidays |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Delta_Normalize |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Delta_Split |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Events_Calc |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Events_ParseRaw |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_ExpandTilde |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_FixPath |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_FullFilePath |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_IsInt |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_ModuloAddition |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_Recur_Split |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_ReturnList |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_SearchPath |
| 0 | 0 | 0 | 0s | 0s | Date::Manip::_sortByLength |
| Line | Stmts. | Exclusive Time | Avg. | Code |
|---|---|---|---|---|
| 1 | package Date::Manip; | |||
| 2 | # Copyright (c) 1995-2008 Sullivan Beck. All rights reserved. | |||
| 3 | # This program is free software; you can redistribute it and/or modify it | |||
| 4 | # under the same terms as Perl itself. | |||
| 5 | ||||
| 6 | ########################################################################### | |||
| 7 | ########################################################################### | |||
| 8 | ||||
| 9 | 3 | 36µs | 12µs | use warnings; # spent 22µs making 1 call to warnings::import |
| 10 | ||||
| 11 | 3 | 692µs | 231µs | use vars qw($OS %Lang %Holiday %Events %Curr %Cnf %Zone $VERSION @ISA @EXPORT); # spent 110µs making 1 call to vars::import |
| 12 | ||||
| 13 | # Determine the type of OS... | |||
| 14 | 1 | 2µs | 2µs | $OS="Unix"; |
| 15 | 1 | 8µs | 8µs | $OS="Windows" if ((defined $^O and |
| 16 | $^O =~ /MSWin32/i || | |||
| 17 | $^O =~ /Windows_95/i || | |||
| 18 | $^O =~ /Windows_NT/i) || | |||
| 19 | (defined $ENV{OS} and | |||
| 20 | $ENV{OS} =~ /MSWin32/i || | |||
| 21 | $ENV{OS} =~ /Windows_95/i || | |||
| 22 | $ENV{OS} =~ /Windows_NT/i)); | |||
| 23 | 1 | 700ns | 700ns | $OS="Unix" if (defined $^O and |
| 24 | $^O =~ /cygwin/i); | |||
| 25 | 1 | 400ns | 400ns | $OS="Netware" if (defined $^O and |
| 26 | $^O =~ /NetWare/i); | |||
| 27 | 1 | 4µs | 4µs | $OS="Mac" if ((defined $^O and |
| 28 | $^O =~ /MacOS/i) || | |||
| 29 | (defined $ENV{OS} and | |||
| 30 | $ENV{OS} =~ /MacOS/i)); | |||
| 31 | 1 | 800ns | 800ns | $OS="MPE" if (defined $^O and |
| 32 | $^O =~ /MPE/i); | |||
| 33 | 1 | 600ns | 600ns | $OS="OS2" if (defined $^O and |
| 34 | $^O =~ /os2/i); | |||
| 35 | 1 | 500ns | 500ns | $OS="VMS" if (defined $^O and |
| 36 | $^O =~ /VMS/i); | |||
| 37 | 1 | 600ns | 600ns | $OS="AIX" if (defined $^O and |
| 38 | $^O =~ /aix/i); | |||
| 39 | ||||
| 40 | # Determine if we're doing taint checking | |||
| 41 | 4 | 37µs | 9µs | $Date::Manip::NoTaint = eval { local $^W=0; eval("#" . substr($^X, 0, 0)); 1 }; |
| 42 | ||||
| 43 | ########################################################################### | |||
| 44 | # CUSTOMIZATION | |||
| 45 | ########################################################################### | |||
| 46 | # | |||
| 47 | # See the section of the POD documentation section CUSTOMIZING DATE::MANIP | |||
| 48 | # below for a complete description of each of these variables. | |||
| 49 | ||||
| 50 | ||||
| 51 | # Location of a the global config file. Tilde (~) expansions are allowed. | |||
| 52 | # This should be set in Date_Init arguments. | |||
| 53 | 1 | 2µs | 2µs | $Cnf{"GlobalCnf"}="/etc/DateManip.cnf"; |
| 54 | 1 | 900ns | 900ns | $Cnf{"IgnoreGlobalCnf"}=""; |
| 55 | ||||
| 56 | # Name of a personal config file and the path to search for it. Tilde (~) | |||
| 57 | # expansions are allowed. This should be set in Date_Init arguments or in | |||
| 58 | # the global config file. | |||
| 59 | ||||
| 60 | 1 | 2µs | 2µs | @Date::Manip::DatePath=(); |
| 61 | 1 | 2µs | 2µs | if ($OS eq "Windows") { |
| 62 | $Cnf{"PathSep"} = ";"; | |||
| 63 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 64 | $Cnf{"PersonalCnfPath"} = "."; | |||
| 65 | ||||
| 66 | } elsif ($OS eq "Netware") { | |||
| 67 | $Cnf{"PathSep"} = ";"; | |||
| 68 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 69 | $Cnf{"PersonalCnfPath"} = "."; | |||
| 70 | ||||
| 71 | } elsif ($OS eq "MPE") { | |||
| 72 | $Cnf{"PathSep"} = ":"; | |||
| 73 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 74 | $Cnf{"PersonalCnfPath"} = "."; | |||
| 75 | ||||
| 76 | } elsif ($OS eq "OS2") { | |||
| 77 | $Cnf{"PathSep"} = ":"; | |||
| 78 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 79 | $Cnf{"PersonalCnfPath"} = "."; | |||
| 80 | ||||
| 81 | } elsif ($OS eq "Mac") { | |||
| 82 | $Cnf{"PathSep"} = ":"; | |||
| 83 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 84 | $Cnf{"PersonalCnfPath"} = "."; | |||
| 85 | ||||
| 86 | } elsif ($OS eq "VMS") { | |||
| 87 | # VMS doesn't like files starting with "." | |||
| 88 | $Cnf{"PathSep"} = ","; | |||
| 89 | $Cnf{"PersonalCnf"} = "Manip.cnf"; | |||
| 90 | $Cnf{"PersonalCnfPath"} = "/sys\$login"; | |||
| 91 | ||||
| 92 | } else { | |||
| 93 | # Unix | |||
| 94 | 1 | 700ns | 700ns | $Cnf{"PathSep"} = ":"; |
| 95 | 1 | 1µs | 1µs | $Cnf{"PersonalCnf"} = ".DateManip.cnf"; |
| 96 | 1 | 1µs | 1µs | $Cnf{"PersonalCnfPath"} = ".:~"; |
| 97 | 1 | 2µs | 2µs | @Date::Manip::DatePath=qw(/bin /usr/bin /usr/local/bin); |
| 98 | } | |||
| 99 | ||||
| 100 | ### Date::Manip variables set in the global or personal config file | |||
| 101 | ||||
| 102 | # Which language to use when parsing dates. | |||
| 103 | 1 | 800ns | 800ns | $Cnf{"Language"}="English"; |
| 104 | ||||
| 105 | # 12/10 = Dec 10 (US) or Oct 12 (anything else) | |||
| 106 | 1 | 900ns | 900ns | $Cnf{"DateFormat"}="US"; |
| 107 | ||||
| 108 | # Local timezone | |||
| 109 | 1 | 500ns | 500ns | $Cnf{"TZ"}=""; |
| 110 | ||||
| 111 | # Timezone to work in (""=local, "IGNORE", or a timezone) | |||
| 112 | 1 | 2µs | 2µs | $Cnf{"ConvTZ"}=""; |
| 113 | ||||
| 114 | # Date::Manip internal format (0=YYYYMMDDHH:MN:SS, 1=YYYYHHMMDDHHMNSS) | |||
| 115 | 1 | 600ns | 600ns | $Cnf{"Internal"}=0; |
| 116 | ||||
| 117 | # First day of the week (1=monday, 7=sunday). ISO 8601 says monday. | |||
| 118 | 1 | 900ns | 900ns | $Cnf{"FirstDay"}=1; |
| 119 | ||||
| 120 | # First and last day of the work week (1=monday, 7=sunday) | |||
| 121 | 1 | 700ns | 700ns | $Cnf{"WorkWeekBeg"}=1; |
| 122 | 1 | 600ns | 600ns | $Cnf{"WorkWeekEnd"}=5; |
| 123 | ||||
| 124 | # If non-nil, a work day is treated as 24 hours long (WorkDayBeg/WorkDayEnd | |||
| 125 | # ignored) | |||
| 126 | 1 | 600ns | 600ns | $Cnf{"WorkDay24Hr"}=0; |
| 127 | ||||
| 128 | # Start and end time of the work day (any time format allowed, seconds | |||
| 129 | # ignored) | |||
| 130 | 1 | 1µs | 1µs | $Cnf{"WorkDayBeg"}="08:00"; |
| 131 | 1 | 600ns | 600ns | $Cnf{"WorkDayEnd"}="17:00"; |
| 132 | ||||
| 133 | # If "today" is a holiday, we look either to "tomorrow" or "yesterday" for | |||
| 134 | # the nearest business day. By default, we'll always look "tomorrow" | |||
| 135 | # first. | |||
| 136 | 1 | 2µs | 2µs | $Cnf{"TomorrowFirst"}=1; |
| 137 | ||||
| 138 | # Erase the old holidays | |||
| 139 | 1 | 800ns | 800ns | $Cnf{"EraseHolidays"}=""; |
| 140 | ||||
| 141 | # Set this to non-zero to be produce completely backwards compatible deltas | |||
| 142 | 1 | 700ns | 700ns | $Cnf{"DeltaSigns"}=0; |
| 143 | ||||
| 144 | # If this is 0, use the ISO 8601 standard that Jan 4 is in week 1. If 1, | |||
| 145 | # make week 1 contain Jan 1. | |||
| 146 | 1 | 600ns | 600ns | $Cnf{"Jan1Week1"}=0; |
| 147 | ||||
| 148 | # 2 digit years fall into the 100 year period given by [ CURR-N, | |||
| 149 | # CURR+(99-N) ] where N is 0-99. Default behavior is 89, but other useful | |||
| 150 | # numbers might be 0 (forced to be this year or later) and 99 (forced to be | |||
| 151 | # this year or earlier). It can also be set to "c" (current century) or | |||
| 152 | # "cNN" (i.e. c18 forces the year to bet 1800-1899). Also accepts the | |||
| 153 | # form cNNNN to give the 100 year period NNNN to NNNN+99. | |||
| 154 | 1 | 1µs | 1µs | $Cnf{"YYtoYYYY"}=89; |
| 155 | ||||
| 156 | # Set this to 1 if you want a long-running script to always update the | |||
| 157 | # timezone. This will slow Date::Manip down. Read the POD documentation. | |||
| 158 | 1 | 600ns | 600ns | $Cnf{"UpdateCurrTZ"}=0; |
| 159 | ||||
| 160 | # Use an international character set. | |||
| 161 | 1 | 500ns | 500ns | $Cnf{"IntCharSet"}=0; |
| 162 | ||||
| 163 | # Use this to force the current date to be set to this: | |||
| 164 | 1 | 700ns | 700ns | $Cnf{"ForceDate"}=""; |
| 165 | ||||
| 166 | # Use this to make "today" mean "today at midnight". | |||
| 167 | 1 | 800ns | 800ns | $Cnf{"TodayIsMidnight"}=0; |
| 168 | ||||
| 169 | ########################################################################### | |||
| 170 | ||||
| 171 | 1 | 34µs | 34µs | require 5.000; |
| 172 | 1 | 1µs | 1µs | require Exporter; |
| 173 | 1 | 9µs | 9µs | @ISA = qw(Exporter); |
| 174 | 1 | 7µs | 7µs | @EXPORT = qw( |
| 175 | DateManipVersion | |||
| 176 | Date_Init | |||
| 177 | ParseDateString | |||
| 178 | ParseDate | |||
| 179 | ParseRecur | |||
| 180 | Date_Cmp | |||
| 181 | DateCalc | |||
| 182 | ParseDateDelta | |||
| 183 | UnixDate | |||
| 184 | Delta_Format | |||
| 185 | Date_GetPrev | |||
| 186 | Date_GetNext | |||
| 187 | Date_SetTime | |||
| 188 | Date_SetDateField | |||
| 189 | Date_IsHoliday | |||
| 190 | Events_List | |||
| 191 | ||||
| 192 | Date_DaysInMonth | |||
| 193 | Date_DayOfWeek | |||
| 194 | Date_SecsSince1970 | |||
| 195 | Date_SecsSince1970GMT | |||
| 196 | Date_DaysSince1BC | |||
| 197 | Date_DayOfYear | |||
| 198 | Date_DaysInYear | |||
| 199 | Date_WeekOfYear | |||
| 200 | Date_LeapYear | |||
| 201 | Date_DaySuffix | |||
| 202 | Date_ConvTZ | |||
| 203 | Date_TimeZone | |||
| 204 | Date_IsWorkDay | |||
| 205 | Date_NextWorkDay | |||
| 206 | Date_PrevWorkDay | |||
| 207 | Date_NearestWorkDay | |||
| 208 | Date_NthDayOfYear | |||
| 209 | ); | |||
| 210 | 3 | 28µs | 9µs | use strict; # spent 9µs making 1 call to strict::import |
| 211 | 3 | 34µs | 11µs | use integer; # spent 12µs making 1 call to integer::import |
| 212 | 3 | 28µs | 9µs | use Carp; # spent 55µs making 1 call to Exporter::import |
| 213 | ||||
| 214 | 3 | 118µs | 40µs | use IO::File; # spent 147µs making 1 call to Exporter::import |
| 215 | ||||
| 216 | 1 | 500ns | 500ns | $VERSION="5.54"; |
| 217 | ||||
| 218 | ######################################################################## | |||
| 219 | ######################################################################## | |||
| 220 | ||||
| 221 | 1 | 1µs | 1µs | $Curr{"InitLang"} = 1; # Whether a language is being init'ed |
| 222 | 1 | 2µs | 2µs | $Curr{"InitDone"} = 0; # Whether Init_Date has been called |
| 223 | 1 | 500ns | 500ns | $Curr{"InitFilesRead"} = 0; |
| 224 | 1 | 700ns | 700ns | $Curr{"ResetWorkDay"} = 1; |
| 225 | 1 | 1µs | 1µs | $Curr{"Debug"} = ""; |
| 226 | 1 | 1µs | 1µs | $Curr{"DebugVal"} = ""; |
| 227 | ||||
| 228 | 1 | 1µs | 1µs | $Holiday{"year"} = 0; |
| 229 | 1 | 1µs | 1µs | $Holiday{"dates"} = {}; |
| 230 | 1 | 800ns | 800ns | $Holiday{"desc"} = {}; |
| 231 | ||||
| 232 | 1 | 1µs | 1µs | $Events{"raw"} = []; |
| 233 | 1 | 800ns | 800ns | $Events{"parsed"} = 0; |
| 234 | 1 | 600ns | 600ns | $Events{"dates"} = []; |
| 235 | 1 | 800ns | 800ns | $Events{"recur"} = []; |
| 236 | ||||
| 237 | ######################################################################## | |||
| 238 | ######################################################################## | |||
| 239 | # THESE ARE THE MAIN ROUTINES | |||
| 240 | ######################################################################## | |||
| 241 | ######################################################################## | |||
| 242 | ||||
| 243 | # Get rid of a problem with old versions of perl | |||
| 244 | 3 | 59µs | 20µs | no strict "vars"; # spent 22µs making 1 call to strict::unimport |
| 245 | # This sorts from longest to shortest element | |||
| 246 | sub _sortByLength { | |||
| 247 | return (length $b <=> length $a); | |||
| 248 | } | |||
| 249 | 3 | 13.7ms | 4.58ms | use strict "vars"; # spent 16µs making 1 call to strict::import |
| 250 | ||||
| 251 | sub DateManipVersion { | |||
| 252 | print "DEBUG: DateManipVersion\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 253 | return $VERSION; | |||
| 254 | } | |||
| 255 | ||||
| 256 | sub Date_Init { | |||
| 257 | print "DEBUG: Date_Init\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 258 | $Curr{"Debug"}=""; | |||
| 259 | ||||
| 260 | my(@args)=@_; | |||
| 261 | $Curr{"InitDone"}=1; | |||
| 262 | local($_)=(); | |||
| 263 | my($internal,$firstday)=(); | |||
| 264 | my($var,$val,$file,@tmp)=(); | |||
| 265 | ||||
| 266 | # InitFilesRead = 0 : no conf files read yet | |||
| 267 | # 1 : global read, no personal read | |||
| 268 | # 2 : personal read | |||
| 269 | ||||
| 270 | $Cnf{"EraseHolidays"}=0; | |||
| 271 | foreach (@args) { | |||
| 272 | s/\s*$//; | |||
| 273 | s/^\s*//; | |||
| 274 | /^(\S+) \s* = \s* (.*)$/x; | |||
| 275 | ($var,$val)=($1,$2); | |||
| 276 | if ($var =~ /^GlobalCnf$/i) { | |||
| 277 | $Cnf{"GlobalCnf"}=$val; | |||
| 278 | if ($val) { | |||
| 279 | $Curr{"InitFilesRead"}=0; | |||
| 280 | EraseHolidays(); | |||
| 281 | } | |||
| 282 | } elsif ($var =~ /^PathSep$/i) { | |||
| 283 | $Cnf{"PathSep"}=$val; | |||
| 284 | } elsif ($var =~ /^PersonalCnf$/i) { | |||
| 285 | $Cnf{"PersonalCnf"}=$val; | |||
| 286 | $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==2); | |||
| 287 | } elsif ($var =~ /^PersonalCnfPath$/i) { | |||
| 288 | $Cnf{"PersonalCnfPath"}=$val; | |||
| 289 | $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==2); | |||
| 290 | } elsif ($var =~ /^IgnoreGlobalCnf$/i) { | |||
| 291 | $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==0); | |||
| 292 | $Cnf{"IgnoreGlobalCnf"}=1; | |||
| 293 | } elsif ($var =~ /^EraseHolidays$/i) { | |||
| 294 | EraseHolidays(); | |||
| 295 | } else { | |||
| 296 | push(@tmp,$_); | |||
| 297 | } | |||
| 298 | } | |||
| 299 | @args=@tmp; | |||
| 300 | ||||
| 301 | # Read global config file | |||
| 302 | if ($Curr{"InitFilesRead"}<1 && ! $Cnf{"IgnoreGlobalCnf"}) { | |||
| 303 | $Curr{"InitFilesRead"}=1; | |||
| 304 | ||||
| 305 | if ($Cnf{"GlobalCnf"}) { | |||
| 306 | $file=_ExpandTilde($Cnf{"GlobalCnf"}); | |||
| 307 | _Date_InitFile($file) if ($file); | |||
| 308 | } | |||
| 309 | } | |||
| 310 | ||||
| 311 | # Read personal config file | |||
| 312 | if ($Curr{"InitFilesRead"}<2) { | |||
| 313 | $Curr{"InitFilesRead"}=2; | |||
| 314 | ||||
| 315 | if ($Cnf{"PersonalCnf"} and $Cnf{"PersonalCnfPath"}) { | |||
| 316 | $file=_SearchPath($Cnf{"PersonalCnf"},$Cnf{"PersonalCnfPath"},"r"); | |||
| 317 | _Date_InitFile($file) if ($file); | |||
| 318 | } | |||
| 319 | } | |||
| 320 | ||||
| 321 | foreach (@args) { | |||
| 322 | s/\s*$//; | |||
| 323 | s/^\s*//; | |||
| 324 | /^(\S+) \s* = \s* (.*)$/x; | |||
| 325 | ($var,$val)=($1,$2); | |||
| 326 | $val="" if (! defined $val); | |||
| 327 | _Date_SetConfigVariable($var,$val); | |||
| 328 | } | |||
| 329 | ||||
| 330 | confess "ERROR: Unknown FirstDay in Date::Manip.\n" | |||
| 331 | if (! _IsInt($Cnf{"FirstDay"},1,7)); | |||
| 332 | confess "ERROR: Unknown WorkWeekBeg in Date::Manip.\n" | |||
| 333 | if (! _IsInt($Cnf{"WorkWeekBeg"},1,7)); | |||
| 334 | confess "ERROR: Unknown WorkWeekEnd in Date::Manip.\n" | |||
| 335 | if (! _IsInt($Cnf{"WorkWeekEnd"},1,7)); | |||
| 336 | confess "ERROR: Invalid WorkWeek in Date::Manip.\n" | |||
| 337 | if ($Cnf{"WorkWeekEnd"} <= $Cnf{"WorkWeekBeg"}); | |||
| 338 | ||||
| 339 | my(%lang, | |||
| 340 | $tmp,%tmp,$tmp2,@tmp2, | |||
| 341 | $i,$j,@tmp3, | |||
| 342 | $zonesrfc,@zones)=(); | |||
| 343 | ||||
| 344 | my($L)=$Cnf{"Language"}; | |||
| 345 | ||||
| 346 | if ($Curr{"InitLang"}) { | |||
| 347 | $Curr{"InitLang"}=0; | |||
| 348 | ||||
| 349 | if ($L eq "English") { | |||
| 350 | _Date_Init_English(\%lang); | |||
| 351 | ||||
| 352 | } elsif ($L eq "French") { | |||
| 353 | _Date_Init_French(\%lang); | |||
| 354 | ||||
| 355 | } elsif ($L eq "Swedish") { | |||
| 356 | _Date_Init_Swedish(\%lang); | |||
| 357 | ||||
| 358 | } elsif ($L eq "German") { | |||
| 359 | _Date_Init_German(\%lang); | |||
| 360 | ||||
| 361 | } elsif ($L eq "Polish") { | |||
| 362 | _Date_Init_Polish(\%lang); | |||
| 363 | ||||
| 364 | } elsif ($L eq "Dutch" || | |||
| 365 | $L eq "Nederlands") { | |||
| 366 | _Date_Init_Dutch(\%lang); | |||
| 367 | ||||
| 368 | } elsif ($L eq "Spanish") { | |||
| 369 | _Date_Init_Spanish(\%lang); | |||
| 370 | ||||
| 371 | } elsif ($L eq "Portuguese") { | |||
| 372 | _Date_Init_Portuguese(\%lang); | |||
| 373 | ||||
| 374 | } elsif ($L eq "Romanian") { | |||
| 375 | _Date_Init_Romanian(\%lang); | |||
| 376 | ||||
| 377 | } elsif ($L eq "Italian") { | |||
| 378 | _Date_Init_Italian(\%lang); | |||
| 379 | ||||
| 380 | } elsif ($L eq "Russian") { | |||
| 381 | _Date_Init_Russian(\%lang); | |||
| 382 | ||||
| 383 | } elsif ($L eq "Turkish") { | |||
| 384 | _Date_Init_Turkish(\%lang); | |||
| 385 | ||||
| 386 | } elsif ($L eq "Danish") { | |||
| 387 | _Date_Init_Danish(\%lang); | |||
| 388 | ||||
| 389 | } elsif ($L eq "Catalan") { | |||
| 390 | _Date_Init_Catalan(\%lang); | |||
| 391 | ||||
| 392 | } else { | |||
| 393 | confess "ERROR: Unknown language in Date::Manip.\n"; | |||
| 394 | } | |||
| 395 | ||||
| 396 | # variables for months | |||
| 397 | # Month = "(jan|january|feb|february ... )" | |||
| 398 | # MonL = [ "Jan","Feb",... ] | |||
| 399 | # MonthL = [ "January","February", ... ] | |||
| 400 | # MonthH = { "january"=>1, "jan"=>1, ... } | |||
| 401 | ||||
| 402 | $Lang{$L}{"MonthH"}={}; | |||
| 403 | $Lang{$L}{"MonthL"}=[]; | |||
| 404 | $Lang{$L}{"MonL"}=[]; | |||
| 405 | _Date_InitLists([$lang{"month_name"}, | |||
| 406 | $lang{"month_abb"}], | |||
| 407 | \$Lang{$L}{"Month"},"lc,sort,back", | |||
| 408 | [$Lang{$L}{"MonthL"}, | |||
| 409 | $Lang{$L}{"MonL"}], | |||
| 410 | [$Lang{$L}{"MonthH"},1]); | |||
| 411 | ||||
| 412 | # variables for day of week | |||
| 413 | # Week = "(mon|monday|tue|tuesday ... )" | |||
| 414 | # WL = [ "M","T",... ] | |||
| 415 | # WkL = [ "Mon","Tue",... ] | |||
| 416 | # WeekL = [ "Monday","Tudesday",... ] | |||
| 417 | # WeekH = { "monday"=>1,"mon"=>1,"m"=>1,... } | |||
| 418 | ||||
| 419 | $Lang{$L}{"WeekH"}={}; | |||
| 420 | $Lang{$L}{"WeekL"}=[]; | |||
| 421 | $Lang{$L}{"WkL"}=[]; | |||
| 422 | $Lang{$L}{"WL"}=[]; | |||
| 423 | _Date_InitLists([$lang{"day_name"}, | |||
| 424 | $lang{"day_abb"}], | |||
| 425 | \$Lang{$L}{"Week"},"lc,sort,back", | |||
| 426 | [$Lang{$L}{"WeekL"}, | |||
| 427 | $Lang{$L}{"WkL"}], | |||
| 428 | [$Lang{$L}{"WeekH"},1]); | |||
| 429 | _Date_InitLists([$lang{"day_char"}], | |||
| 430 | "","lc", | |||
| 431 | [$Lang{$L}{"WL"}], | |||
| 432 | [\%tmp,1]); | |||
| 433 | %{ $Lang{$L}{"WeekH"} } = | |||
| 434 | (%{ $Lang{$L}{"WeekH"} },%tmp); | |||
| 435 | ||||
| 436 | # variables for last | |||
| 437 | # Last = "(last)" | |||
| 438 | # LastL = [ "last" ] | |||
| 439 | # Each = "(each)" | |||
| 440 | # EachL = [ "each" ] | |||
| 441 | # variables for day of month | |||
| 442 | # DoM = "(1st|first ... 31st)" | |||
| 443 | # DoML = [ "1st","2nd",... "31st" ] | |||
| 444 | # DoMH = { "1st"=>1,"first"=>1, ... "31st"=>31 } | |||
| 445 | # variables for week of month | |||
| 446 | # WoM = "(1st|first| ... 5th|last)" | |||
| 447 | # WoMH = { "1st"=>1, ... "5th"=>5,"last"=>-1 } | |||
| 448 | ||||
| 449 | $Lang{$L}{"LastL"}=$lang{"last"}; | |||
| 450 | _Date_InitStrings($lang{"last"}, | |||
| 451 | \$Lang{$L}{"Last"},"lc,sort"); | |||
| 452 | ||||
| 453 | $Lang{$L}{"EachL"}=$lang{"each"}; | |||
| 454 | _Date_InitStrings($lang{"each"}, | |||
| 455 | \$Lang{$L}{"Each"},"lc,sort"); | |||
| 456 | ||||
| 457 | $Lang{$L}{"DoMH"}={}; | |||
| 458 | $Lang{$L}{"DoML"}=[]; | |||
| 459 | _Date_InitLists([$lang{"num_suff"}, | |||
| 460 | $lang{"num_word"}], | |||
| 461 | \$Lang{$L}{"DoM"},"lc,sort,back,escape", | |||
| 462 | [$Lang{$L}{"DoML"}, | |||
| 463 | \@tmp], | |||
| 464 | [$Lang{$L}{"DoMH"},1]); | |||
| 465 | ||||
| 466 | @tmp=(); | |||
| 467 | foreach $tmp (keys %{ $Lang{$L}{"DoMH"} }) { | |||
| 468 | $tmp2=$Lang{$L}{"DoMH"}{$tmp}; | |||
| 469 | if ($tmp2<6) { | |||
| 470 | $Lang{$L}{"WoMH"}{$tmp} = $tmp2; | |||
| 471 | push(@tmp,$tmp); | |||
| 472 | } | |||
| 473 | } | |||
| 474 | foreach $tmp (@{ $Lang{$L}{"LastL"} }) { | |||
| 475 | $Lang{$L}{"WoMH"}{$tmp} = -1; | |||
| 476 | push(@tmp,$tmp); | |||
| 477 | } | |||
| 478 | _Date_InitStrings(\@tmp,\$Lang{$L}{"WoM"}, | |||
| 479 | "lc,sort,back,escape"); | |||
| 480 | ||||
| 481 | # variables for AM or PM | |||
| 482 | # AM = "(am)" | |||
| 483 | # PM = "(pm)" | |||
| 484 | # AmPm = "(am|pm)" | |||
| 485 | # AMstr = "AM" | |||
| 486 | # PMstr = "PM" | |||
| 487 | ||||
| 488 | _Date_InitStrings($lang{"am"},\$Lang{$L}{"AM"},"lc,sort,escape"); | |||
| 489 | _Date_InitStrings($lang{"pm"},\$Lang{$L}{"PM"},"lc,sort,escape"); | |||
| 490 | _Date_InitStrings([ @{$lang{"am"}},@{$lang{"pm"}} ],\$Lang{$L}{"AmPm"}, | |||
| 491 | "lc,back,sort,escape"); | |||
| 492 | $Lang{$L}{"AMstr"}=$lang{"am"}[0]; | |||
| 493 | $Lang{$L}{"PMstr"}=$lang{"pm"}[0]; | |||
| 494 | ||||
| 495 | # variables for expressions used in parsing deltas | |||
| 496 | # Yabb = "(?:y|yr|year|years)" | |||
| 497 | # Mabb = similar for months | |||
| 498 | # Wabb = similar for weeks | |||
| 499 | # Dabb = similar for days | |||
| 500 | # Habb = similar for hours | |||
| 501 | # MNabb = similar for minutes | |||
| 502 | # Sabb = similar for seconds | |||
| 503 | # Repl = { "abb"=>"replacement" } | |||
| 504 | # Whenever an abbreviation could potentially refer to two different | |||
| 505 | # strings (M standing for Minutes or Months), the abbreviation must | |||
| 506 | # be listed in Repl instead of in the appropriate Xabb values. This | |||
| 507 | # only applies to abbreviations which are substrings of other values | |||
| 508 | # (so there is no confusion between Mn and Month). | |||
| 509 | ||||
| 510 | _Date_InitStrings($lang{"years"} ,\$Lang{$L}{"Yabb"}, "lc,sort"); | |||
| 511 | _Date_InitStrings($lang{"months"} ,\$Lang{$L}{"Mabb"}, "lc,sort"); | |||
| 512 | _Date_InitStrings($lang{"weeks"} ,\$Lang{$L}{"Wabb"}, "lc,sort"); | |||
| 513 | _Date_InitStrings($lang{"days"} ,\$Lang{$L}{"Dabb"}, "lc,sort"); | |||
| 514 | _Date_InitStrings($lang{"hours"} ,\$Lang{$L}{"Habb"}, "lc,sort"); | |||
| 515 | _Date_InitStrings($lang{"minutes"},\$Lang{$L}{"MNabb"},"lc,sort"); | |||
| 516 | _Date_InitStrings($lang{"seconds"},\$Lang{$L}{"Sabb"}, "lc,sort"); | |||
| 517 | $Lang{$L}{"Repl"}={}; | |||
| 518 | _Date_InitHash($lang{"replace"},undef,"lc",$Lang{$L}{"Repl"}); | |||
| 519 | ||||
| 520 | # variables for special dates that are offsets from now | |||
| 521 | # Now = "now" | |||
| 522 | # Today = "today" | |||
| 523 | # Offset = "(yesterday|tomorrow)" | |||
| 524 | # OffsetH = { "yesterday"=>"-0:0:0:1:0:0:0",... ] | |||
| 525 | # Times = "(noon|midnight)" | |||
| 526 | # TimesH = { "noon"=>"12:00:00","midnight"=>"00:00:00" } | |||
| 527 | # SepHM = hour/minute separator | |||
| 528 | # SepMS = minute/second separator | |||
| 529 | # SepSS = second/fraction separator | |||
| 530 | ||||
| 531 | $Lang{$L}{"TimesH"}={}; | |||
| 532 | _Date_InitHash($lang{"times"}, | |||
| 533 | \$Lang{$L}{"Times"},"lc,sort,back", | |||
| 534 | $Lang{$L}{"TimesH"}); | |||
| 535 | _Date_InitStrings($lang{"now"},\$Lang{$L}{"Now"},"lc,sort"); | |||
| 536 | _Date_InitStrings($lang{"today"},\$Lang{$L}{"Today"},"lc,sort"); | |||
| 537 | $Lang{$L}{"OffsetH"}={}; | |||
| 538 | _Date_InitHash($lang{"offset"}, | |||
| 539 | \$Lang{$L}{"Offset"},"lc,sort,back", | |||
| 540 | $Lang{$L}{"OffsetH"}); | |||
| 541 | $Lang{$L}{"SepHM"}=$lang{"sephm"}; | |||
| 542 | $Lang{$L}{"SepMS"}=$lang{"sepms"}; | |||
| 543 | $Lang{$L}{"SepSS"}=$lang{"sepss"}; | |||
| 544 | ||||
| 545 | # variables for time zones | |||
| 546 | # zones = regular expression with all zone names (EST) | |||
| 547 | # n2o = a hash of all parsable zone names with their offsets | |||
| 548 | # tzones = reguar expression with all tzdata timezones (US/Eastern) | |||
| 549 | # tz2z = hash of all tzdata timezones to full timezone (EST#EDT) | |||
| 550 | ||||
| 551 | $zonesrfc= | |||
| 552 | "idlw -1200 ". # International Date Line West | |||
| 553 | "nt -1100 ". # Nome | |||
| 554 | "hst -1000 ". # Hawaii Standard | |||
| 555 | "cat -1000 ". # Central Alaska | |||
| 556 | "ahst -1000 ". # Alaska-Hawaii Standard | |||
| 557 | "akst -0900 ". # Alaska Standard | |||
| 558 | "yst -0900 ". # Yukon Standard | |||
| 559 | "hdt -0900 ". # Hawaii Daylight | |||
| 560 | "akdt -0800 ". # Alaska Daylight | |||
| 561 | "ydt -0800 ". # Yukon Daylight | |||
| 562 | "pst -0800 ". # Pacific Standard | |||
| 563 | "pdt -0700 ". # Pacific Daylight | |||
| 564 | "mst -0700 ". # Mountain Standard | |||
| 565 | "mdt -0600 ". # Mountain Daylight | |||
| 566 | "cst -0600 ". # Central Standard | |||
| 567 | "cdt -0500 ". # Central Daylight | |||
| 568 | "est -0500 ". # Eastern Standard | |||
| 569 | "act -0500 ". # Brazil, Acre | |||
| 570 | "pet -0500 ". # Peruvian time | |||
| 571 | "vet -0430 ". # Venezuela | |||
| 572 | "sat -0400 ". # Chile | |||
| 573 | "clt -0400 ". # Chile Standard | |||
| 574 | "clst -0400 ". # Chile Standard | |||
| 575 | "bot -0400 ". # Bolivia | |||
| 576 | "amt -0400 ". # Brazil, Amazon | |||
| 577 | "acst -0400 ". # Brazil, Acre Daylight | |||
| 578 | "edt -0400 ". # Eastern Daylight | |||
| 579 | "ast -0400 ". # Atlantic Standard | |||
| 580 | #"nst -0330 ". # Newfoundland Standard nst=North Sumatra +0630 | |||
| 581 | "nft -0330 ". # Newfoundland | |||
| 582 | #"gst -0300 ". # Greenland Standard gst=Guam Standard +1000 | |||
| 583 | "cldt -0300 ". # Chile Daylight | |||
| 584 | #"bst -0300 ". # Brazil Standard bst=British Summer +0100 | |||
| 585 | "brt -0300 ". # Brazil Standard (official time) | |||
| 586 | #"brst -0300 ". # Brazil Standard | |||
| 587 | "adt -0300 ". # Atlantic Daylight | |||
| 588 | "art -0300 ". # Argentina | |||
| 589 | "arst -0200 ". # Argentina, Daylight | |||
| 590 | "amst -0300 ". # Brazil, Amazon Daylight | |||
| 591 | "uyt -0300 ". # Uruguay | |||
| 592 | "ndt -0230 ". # Newfoundland Daylight | |||
| 593 | "brst -0200 ". # Brazil Daylight (official time) | |||
| 594 | "fnt -0200 ". # Brazil, Fernando de Noronha | |||
| 595 | "at -0200 ". # Azores | |||
| 596 | "uyst -0200 ". # Uruguay | |||
| 597 | "wat -0100 ". # West Africa | |||
| 598 | "fnst -0100 ". # Brazil, Fernando de Noronha Daylight | |||
| 599 | "gmt +0000 ". # Greenwich Mean | |||
| 600 | "ut +0000 ". # Universal | |||
| 601 | "utc +0000 ". # Universal (Coordinated) | |||
| 602 | "wet +0000 ". # Western European | |||
| 603 | "cet +0100 ". # Central European | |||
| 604 | "fwt +0100 ". # French Winter | |||
| 605 | "met +0100 ". # Middle European | |||
| 606 | "mez +0100 ". # Middle European | |||
| 607 | "mewt +0100 ". # Middle European Winter | |||
| 608 | "swt +0100 ". # Swedish Winter | |||
| 609 | "bst +0100 ". # British Summer bst=Brazil standard -0300 | |||
| 610 | "gb +0100 ". # GMT with daylight savings | |||
| 611 | "west +0100 ". # Western European Daylight | |||
| 612 | "eet +0200 ". # Eastern Europe, USSR Zone 1 | |||
| 613 | "cest +0200 ". # Central European Summer | |||
| 614 | "fst +0200 ". # French Summer | |||
| 615 | "ist +0200 ". # Israel standard | |||
| 616 | "mest +0200 ". # Middle European Summer | |||
| 617 | "mesz +0200 ". # Middle European Summer | |||
| 618 | "metdst +0200 ". # An alias for mest used by HP-UX | |||
| 619 | "sast +0200 ". # South African Standard | |||
| 620 | "sst +0200 ". # Swedish Summer sst=South Sumatra +0700 | |||
| 621 | "bt +0300 ". # Baghdad, USSR Zone 2 | |||
| 622 | "eest +0300 ". # Eastern Europe Summer | |||
| 623 | "eetdst +0300 ". # An alias for eest used by HP-UX | |||
| 624 | "eetedt +0300 ". # Eastern Europe, USSR Zone 1 | |||
| 625 | "idt +0300 ". # Israel Daylight | |||
| 626 | "msk +0300 ". # Moscow | |||
| 627 | "eat +0300 ". # East Africa | |||
| 628 | "it +0330 ". # Iran | |||
| 629 | "zp4 +0400 ". # USSR Zone 3 | |||
| 630 | "msd +0400 ". # Moscow Daylight | |||
| 631 | "zp5 +0500 ". # USSR Zone 4 | |||
| 632 | "yekt +0500 ". # Yeakaterinburg time zone, Russia | |||
| 633 | "yekst +0500 ". # Yeakaterinburg summer time zone, Russia | |||
| 634 | "ist +0530 ". # Indian Standard | |||
| 635 | "zp6 +0600 ". # USSR Zone 5 | |||
| 636 | "novt +0600 ". # Novosibirsk winter time zone, Russia | |||
| 637 | "omst +0600 ". # Omsk time zone, Russia | |||
| 638 | "nst +0630 ". # North Sumatra nst=Newfoundland Std -0330 | |||
| 639 | #"sst +0700 ". # South Sumatra, USSR Zone 6 sst=Swedish Summer +0200 | |||
| 640 | "javt +0700 ". # Java | |||
| 641 | "ict +0700 ". # Indo China Time | |||
| 642 | "novst +0700 ". # Novosibirsk summer time zone, Russia | |||
| 643 | "krat +0700 ". # Krasnoyarsk, Russia | |||
| 644 | "myt +0800 ". # Malaysia | |||
| 645 | "hkt +0800 ". # Hong Kong | |||
| 646 | "sgt +0800 ". # Singapore | |||
| 647 | "cct +0800 ". # China Coast, USSR Zone 7 | |||
| 648 | "krast +0800 ". # Krasnoyarsk, Russia Daylight | |||
| 649 | "awst +0800 ". # Australian Western Standard | |||
| 650 | "wst +0800 ". # West Australian Standard | |||
| 651 | "pht +0800 ". # Asia Manila | |||
| 652 | "kst +0900 ". # Republic of Korea | |||
| 653 | "jst +0900 ". # Japan Standard, USSR Zone 8 | |||
| 654 | "rok +0900 ". # Republic of Korea | |||
| 655 | "acst +0930 ". # Australian Central Standard | |||
| 656 | "cast +0930 ". # Central Australian Standard | |||
| 657 | "aest +1000 ". # Australian Eastern Standard | |||
| 658 | "east +1000 ". # Eastern Australian Standard | |||
| 659 | "gst +1000 ". # Guam Standard, USSR Zone 9 gst=Greenland Std -0300 | |||
| 660 | "chst +1000 ". # Guam Standard, USSR Zone 9 gst=Greenland Std -0300 | |||
| 661 | "acdt +1030 ". # Australian Central Daylight | |||
| 662 | "cadt +1030 ". # Central Australian Daylight | |||
| 663 | "aedt +1100 ". # Australian Eastern Daylight | |||
| 664 | "eadt +1100 ". # Eastern Australian Daylight | |||
| 665 | "idle +1200 ". # International Date Line East | |||
| 666 | "nzst +1200 ". # New Zealand Standard | |||
| 667 | "nzt +1200 ". # New Zealand | |||
| 668 | "nzdt +1300 ". # New Zealand Daylight | |||
| 669 | "z +0000 ". | |||
| 670 | "a +0100 b +0200 c +0300 d +0400 e +0500 f +0600 g +0700 h +0800 ". | |||
| 671 | "i +0900 k +1000 l +1100 m +1200 ". | |||
| 672 | "n -0100 o -0200 p -0300 q -0400 r -0500 s -0600 t -0700 u -0800 ". | |||
| 673 | "v -0900 w -1000 x -1100 y -1200"; | |||
| 674 | ||||
| 675 | $Zone{"n2o"} = {}; | |||
| 676 | ($Zone{"zones"},%{ $Zone{"n2o"} })= | |||
| 677 | _Date_Regexp($zonesrfc,"sort,lc,under,back", | |||
| 678 | "keys"); | |||
| 679 | ||||
| 680 | $tmp= | |||
| 681 | "US/Pacific PST8PDT ". | |||
| 682 | "US/Mountain MST7MDT ". | |||
| 683 | "US/Central CST6CDT ". | |||
| 684 | "US/Eastern EST5EDT ". | |||
| 685 | "Canada/Pacific PST8PDT ". | |||
| 686 | "Canada/Mountain MST7MDT ". | |||
| 687 | "Canada/Central CST6CDT ". | |||
| 688 | "Canada/Eastern EST5EDT"; | |||
| 689 | ||||
| 690 | $Zone{"tz2z"} = {}; | |||
| 691 | ($Zone{"tzones"},%{ $Zone{"tz2z"} })= | |||
| 692 | _Date_Regexp($tmp,"lc,under,back","keys"); | |||
| 693 | $Cnf{"TZ"}=Date_TimeZone(); | |||
| 694 | ||||
| 695 | # misc. variables | |||
| 696 | # At = "(?:at)" | |||
| 697 | # Of = "(?:in|of)" | |||
| 698 | # On = "(?:on)" | |||
| 699 | # Future = "(?:in)" | |||
| 700 | # Later = "(?:later)" | |||
| 701 | # Past = "(?:ago)" | |||
| 702 | # Next = "(?:next)" | |||
| 703 | # Prev = "(?:last|previous)" | |||
| 704 | ||||
| 705 | _Date_InitStrings($lang{"at"}, \$Lang{$L}{"At"}, "lc,sort"); | |||
| 706 | _Date_InitStrings($lang{"on"}, \$Lang{$L}{"On"}, "lc,sort"); | |||
| 707 | _Date_InitStrings($lang{"future"},\$Lang{$L}{"Future"}, "lc,sort"); | |||
| 708 | _Date_InitStrings($lang{"later"}, \$Lang{$L}{"Later"}, "lc,sort"); | |||
| 709 | _Date_InitStrings($lang{"past"}, \$Lang{$L}{"Past"}, "lc,sort"); | |||
| 710 | _Date_InitStrings($lang{"next"}, \$Lang{$L}{"Next"}, "lc,sort"); | |||
| 711 | _Date_InitStrings($lang{"prev"}, \$Lang{$L}{"Prev"}, "lc,sort"); | |||
| 712 | _Date_InitStrings($lang{"of"}, \$Lang{$L}{"Of"}, "lc,sort"); | |||
| 713 | ||||
| 714 | # calc mode variables | |||
| 715 | # Approx = "(?:approximately)" | |||
| 716 | # Exact = "(?:exactly)" | |||
| 717 | # Business = "(?:business)" | |||
| 718 | ||||
| 719 | _Date_InitStrings($lang{"exact"}, \$Lang{$L}{"Exact"}, "lc,sort"); | |||
| 720 | _Date_InitStrings($lang{"approx"}, \$Lang{$L}{"Approx"}, "lc,sort"); | |||
| 721 | _Date_InitStrings($lang{"business"},\$Lang{$L}{"Business"},"lc,sort"); | |||
| 722 | ||||
| 723 | ############### END OF LANGUAGE INITIALIZATION | |||
| 724 | } | |||
| 725 | ||||
| 726 | if ($Curr{"ResetWorkDay"}) { | |||
| 727 | my($h1,$m1,$h2,$m2)=(); | |||
| 728 | if ($Cnf{"WorkDay24Hr"}) { | |||
| 729 | ($Curr{"WDBh"},$Curr{"WDBm"})=(0,0); | |||
| 730 | ($Curr{"WDEh"},$Curr{"WDEm"})=(24,0); | |||
| 731 | $Curr{"WDlen"}=24*60; | |||
| 732 | $Cnf{"WorkDayBeg"}="00:00"; | |||
| 733 | $Cnf{"WorkDayEnd"}="23:59"; | |||
| 734 | ||||
| 735 | } else { | |||
| 736 | confess "ERROR: Invalid WorkDayBeg in Date::Manip.\n" | |||
| 737 | if (! (($h1,$m1)=_CheckTime($Cnf{"WorkDayBeg"}))); | |||
| 738 | $Cnf{"WorkDayBeg"}="$h1:$m1"; | |||
| 739 | confess "ERROR: Invalid WorkDayEnd in Date::Manip.\n" | |||
| 740 | if (! (($h2,$m2)=_CheckTime($Cnf{"WorkDayEnd"}))); | |||
| 741 | $Cnf{"WorkDayEnd"}="$h2:$m2"; | |||
| 742 | ||||
| 743 | ($Curr{"WDBh"},$Curr{"WDBm"})=($h1,$m1); | |||
| 744 | ($Curr{"WDEh"},$Curr{"WDEm"})=($h2,$m2); | |||
| 745 | ||||
| 746 | # Work day length = h1:m1 or 0:len (len minutes) | |||
| 747 | $h1=$h2-$h1; | |||
| 748 | $m1=$m2-$m1; | |||
| 749 | if ($m1<0) { | |||
| 750 | $h1--; | |||
| 751 | $m1+=60; | |||
| 752 | } | |||
| 753 | $Curr{"WDlen"}=$h1*60+$m1; | |||
| 754 | } | |||
| 755 | $Curr{"ResetWorkDay"}=0; | |||
| 756 | } | |||
| 757 | ||||
| 758 | # current time | |||
| 759 | my($s,$mn,$h,$d,$m,$y,$wday,$yday,$isdst,$ampm,$wk)=(); | |||
| 760 | if ($Cnf{"ForceDate"}=~ | |||
| 761 | /^(\d{4})-(\d{2})-(\d{2})-(\d{2}):(\d{2}):(\d{2})$/) { | |||
| 762 | ($y,$m,$d,$h,$mn,$s)=($1,$2,$3,$4,$5,$6); | |||
| 763 | } else { | |||
| 764 | ($s,$mn,$h,$d,$m,$y,$wday,$yday,$isdst)=localtime(time); | |||
| 765 | $y+=1900; | |||
| 766 | $m++; | |||
| 767 | } | |||
| 768 | _Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk); | |||
| 769 | $Curr{"Y"}=$y; | |||
| 770 | $Curr{"M"}=$m; | |||
| 771 | $Curr{"D"}=$d; | |||
| 772 | $Curr{"H"}=$h; | |||
| 773 | $Curr{"Mn"}=$mn; | |||
| 774 | $Curr{"S"}=$s; | |||
| 775 | $Curr{"AmPm"}=$ampm; | |||
| 776 | $Curr{"Now"}=_Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 777 | if ($Cnf{"TodayIsMidnight"}) { | |||
| 778 | $Curr{"Today"}=_Date_Join($y,$m,$d,0,0,0); | |||
| 779 | } else { | |||
| 780 | $Curr{"Today"}=$Curr{"Now"}; | |||
| 781 | } | |||
| 782 | ||||
| 783 | $Curr{"Debug"}=$Curr{"DebugVal"}; | |||
| 784 | ||||
| 785 | # If we're in array context, let's return a list of config variables | |||
| 786 | # that could be passed to Date_Init to get the same state as we're | |||
| 787 | # currently in. | |||
| 788 | if (wantarray) { | |||
| 789 | # Some special variables that have to be in a specific order | |||
| 790 | my(@special)=qw(IgnoreGlobalCnf GlobalCnf PersonalCnf PersonalCnfPath); | |||
| 791 | my(%tmp)=map { $_,1 } @special; | |||
| 792 | my(@tmp,$key,$val); | |||
| 793 | foreach $key (@special) { | |||
| 794 | $val=$Cnf{$key}; | |||
| 795 | push(@tmp,"$key=$val"); | |||
| 796 | } | |||
| 797 | foreach $key (keys %Cnf) { | |||
| 798 | next if (exists $tmp{$key}); | |||
| 799 | $val=$Cnf{$key}; | |||
| 800 | push(@tmp,"$key=$val"); | |||
| 801 | } | |||
| 802 | return @tmp; | |||
| 803 | } | |||
| 804 | return (); | |||
| 805 | } | |||
| 806 | ||||
| 807 | sub ParseDateString { | |||
| 808 | print "DEBUG: ParseDateString\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 809 | local($_)=@_; | |||
| 810 | return "" if (! $_); | |||
| 811 | ||||
| 812 | my($y,$m,$d,$h,$mn,$s,$i,$wofm,$dofw,$wk,$tmp,$z,$num,$err,$iso,$ampm)=(); | |||
| 813 | my($date,$z2,$delta,$from,$falsefrom,$to,$which,$midnight)=(); | |||
| 814 | ||||
| 815 | # We only need to reinitialize if we have to determine what NOW is. | |||
| 816 | Date_Init() if (! $Curr{"InitDone"} or $Cnf{"UpdateCurrTZ"}); | |||
| 817 | ||||
| 818 | my($L)=$Cnf{"Language"}; | |||
| 819 | my($type)=$Cnf{"DateFormat"}; | |||
| 820 | ||||
| 821 | # Mode is set in DateCalc. ParseDate only overrides it if the string | |||
| 822 | # contains a mode. | |||
| 823 | if ($Lang{$L}{"Exact"} && | |||
| 824 | s/$Lang{$L}{"Exact"}//) { | |||
| 825 | $Curr{"Mode"}=0; | |||
| 826 | } elsif ($Lang{$L}{"Approx"} && | |||
| 827 | s/$Lang{$L}{"Approx"}//) { | |||
| 828 | $Curr{"Mode"}=1; | |||
| 829 | } elsif ($Lang{$L}{"Business"} && | |||
| 830 | s/$Lang{$L}{"Business"}//) { | |||
| 831 | $Curr{"Mode"}=2; | |||
| 832 | } elsif (! exists $Curr{"Mode"}) { | |||
| 833 | $Curr{"Mode"}=0; | |||
| 834 | } | |||
| 835 | ||||
| 836 | # Unfortunately, some deltas can be parsed as dates. An example is | |||
| 837 | # 1 second == 1 2nd == 1 2 | |||
| 838 | # But, some dates can be parsed as deltas. The most important being: | |||
| 839 | # 1998010101:00:00 | |||
| 840 | # | |||
| 841 | # We'll check to see if a "date" can be parsed as a delta. If so, we'll | |||
| 842 | # assume that it is a delta (since they are much simpler, it is much | |||
| 843 | # less likely that we'll mistake a delta for a date than vice versa) | |||
| 844 | # unless it is an ISO-8601 date. | |||
| 845 | # | |||
| 846 | # This is important because we are using DateCalc to test whether a | |||
| 847 | # string is a date or a delta. Dates are tested first, so we need to | |||
| 848 | # be able to pass a delta into this routine and have it correctly NOT | |||
| 849 | # interpreted as a date. | |||
| 850 | # | |||
| 851 | # We will insist that the string contain something other than digits and | |||
| 852 | # colons so that the following will get correctly interpreted as a date | |||
| 853 | # rather than a delta: | |||
| 854 | # 12:30 | |||
| 855 | # 19980101 | |||
| 856 | ||||
| 857 | $delta=""; | |||
| 858 | $delta=ParseDateDelta($_) if (/[^:0-9]/); | |||
| 859 | ||||
| 860 | # Put parse in a simple loop for an easy exit. | |||
| 861 | PARSE: { | |||
| 862 | my(@tmp)=_Date_Split($_); | |||
| 863 | if (@tmp) { | |||
| 864 | ($y,$m,$d,$h,$mn,$s)=@tmp; | |||
| 865 | last PARSE; | |||
| 866 | } | |||
| 867 | ||||
| 868 | # Fundamental regular expressions | |||
| 869 | ||||
| 870 | my($month)=$Lang{$L}{"Month"}; # (jan|january|...) | |||
| 871 | my(%month)=%{ $Lang{$L}{"MonthH"} }; # { jan=>1, ... } | |||
| 872 | my($week)=$Lang{$L}{"Week"}; # (mon|monday|...) | |||
| 873 | my(%week)=%{ $Lang{$L}{"WeekH"} }; # { mon=>1, monday=>1, ... } | |||
| 874 | my($wom)=$Lang{$L}{"WoM"}; # (1st|...|fifth|last) | |||
| 875 | my(%wom)=%{ $Lang{$L}{"WoMH"} }; # { 1st=>1,... fifth=>5,last=>-1 } | |||
| 876 | my($dom)=$Lang{$L}{"DoM"}; # (1st|first|...31st) | |||
| 877 | my(%dom)=%{ $Lang{$L}{"DoMH"} }; # { 1st=>1, first=>1, ... } | |||
| 878 | my($ampmexp)=$Lang{$L}{"AmPm"}; # (am|pm) | |||
| 879 | my($timeexp)=$Lang{$L}{"Times"}; # (noon|midnight) | |||
| 880 | my($now)=$Lang{$L}{"Now"}; # now | |||
| 881 | my($today)=$Lang{$L}{"Today"}; # today | |||
| 882 | my($offset)=$Lang{$L}{"Offset"}; # (yesterday|tomorrow) | |||
| 883 | my($zone)=$Zone{"zones"}; # (edt|est|...) | |||
| 884 | my($day)='\s*'.$Lang{$L}{"Dabb"}; # \s*(?:d|day|days) | |||
| 885 | my($mabb)='\s*'.$Lang{$L}{"Mabb"}; # \s*(?:mon|month|months) | |||
| 886 | my($wkabb)='\s*'.$Lang{$L}{"Wabb"}; # \s*(?:w|wk|week|weeks) | |||
| 887 | my($next)='\s*'.$Lang{$L}{"Next"}; # \s*(?:next) | |||
| 888 | my($prev)='\s*'.$Lang{$L}{"Prev"}; # \s*(?:last|previous) | |||
| 889 | my($past)='\s*'.$Lang{$L}{"Past"}; # \s*(?:ago) | |||
| 890 | my($future)='\s*'.$Lang{$L}{"Future"}; # \s*(?:in) | |||
| 891 | my($later)='\s*'.$Lang{$L}{"Later"}; # \s*(?:later) | |||
| 892 | my($at)=$Lang{$L}{"At"}; # (?:at) | |||
| 893 | my($of)='\s*'.$Lang{$L}{"Of"}; # \s*(?:in|of) | |||
| 894 | my($on)='(?:\s*'.$Lang{$L}{"On"}.'\s*|\s+)'; | |||
| 895 | # \s*(?:on)\s* or \s+ | |||
| 896 | my($last)='\s*'.$Lang{$L}{"Last"}; # \s*(?:last) | |||
| 897 | my($hm)=$Lang{$L}{"SepHM"}; # : | |||
| 898 | my($ms)=$Lang{$L}{"SepMS"}; # : | |||
| 899 | my($ss)=$Lang{$L}{"SepSS"}; # . | |||
| 900 | ||||
| 901 | # Other regular expressions | |||
| 902 | ||||
| 903 | my($D4)='(\d{4})'; # 4 digits (yr) | |||
| 904 | my($YY)='(\d{4}|\d{2})'; # 2 or 4 digits (yr) | |||
| 905 | my($DD)='(\d{2})'; # 2 digits (mon/day/hr/min/sec) | |||
| 906 | my($D) ='(\d{1,2})'; # 1 or 2 digit (mon/day/hr) | |||
| 907 | my($FS)="(?:$ss\\d+)?"; # fractional secs | |||
| 908 | my($sep)='[\/.-]'; # non-ISO8601 m/d/yy separators | |||
| 909 | # absolute time zone +0700 (GMT) | |||
| 910 | my($hzone)='(?:[0-1][0-9]|2[0-3])'; # 00 - 23 | |||
| 911 | my($mzone)='(?:[0-5][0-9])'; # 00 - 59 | |||
| 912 | my($zone2)='(?:\s*([+-](?:'."$hzone$mzone|$hzone:$mzone|$hzone))". | |||
| 913 | # +0700 +07:00 -07 | |||
| 914 | '(?:\s*\([^)]+\))?)'; # (GMT) | |||
| 915 | ||||
| 916 | # A regular expression for the time EXCEPT for the hour part | |||
| 917 | my($mnsec)="$hm$DD(?:$ms$DD$FS)?(?:\\s*$ampmexp)?"; | |||
| 918 | ||||
| 919 | # A special regular expression for /YYYY:HH:MN:SS used by Apache | |||
| 920 | my($apachetime)='(/\d{4}):' . "$DD$hm$DD$ms$DD"; | |||
| 921 | ||||
| 922 | my($time)=""; | |||
| 923 | $ampm=""; | |||
| 924 | $date=""; | |||
| 925 | ||||
| 926 | # Substitute all special time expressions. | |||
| 927 | if (/(^|[^a-z])$timeexp($|[^a-z])/i) { | |||
| 928 | $tmp=$2; | |||
| 929 | $tmp=$Lang{$L}{"TimesH"}{lc($tmp)}; | |||
| 930 | s/(^|[^a-z])$timeexp($|[^a-z])/$1 $tmp $3/i; | |||
| 931 | } | |||
| 932 | ||||
| 933 | # Remove some punctuation | |||
| 934 | s/[,]/ /g; | |||
| 935 | ||||
| 936 | # When we have a digit followed immediately by a timezone (7EST), we | |||
| 937 | # will put a space between the digit, EXCEPT in the case of a single | |||
| 938 | # character military timezone. If the single character is followed | |||
| 939 | # by anything, no space is added. | |||
| 940 | $tmp = ""; | |||
| 941 | while ( s/^(.*?\d)$zone(\s|$|[0-9])/$3/i ) { | |||
| 942 | my($bef,$z,$aft) = ($1,$2,$3); | |||
| 943 | if (length($z) != 1 || length($aft) == 0) { | |||
| 944 | $tmp .= "$bef $z"; | |||
| 945 | } else { | |||
| 946 | $tmp .= "$bef$z"; | |||
| 947 | } | |||
| 948 | } | |||
| 949 | $_ = "$tmp$_"; | |||
| 950 | $zone = '\s+' . $zone . '(?:\s+|$)'; | |||
| 951 | ||||
| 952 | # Remove the time | |||
| 953 | $iso=1; | |||
| 954 | $midnight=0; | |||
| 955 | $from="24${hm}00(?:${ms}00)?"; | |||
| 956 | $falsefrom="${hm}24${ms}00"; # Don't trap XX:24:00 | |||
| 957 | $to="00${hm}00${ms}00"; | |||
| 958 | $midnight=1 if (!/$falsefrom/ && s/$from/$to/); | |||
| 959 | ||||
| 960 | $h=$mn=$s=0; | |||
| 961 | if (/$D$mnsec/i || /$ampmexp/i) { | |||
| 962 | $iso=0; | |||
| 963 | $tmp=0; | |||
| 964 | $tmp=1 if (/$mnsec$zone2?\s*$/i or /$mnsec$zone\s*$/i); | |||
| 965 | $tmp=0 if (/$ampmexp/i); | |||
| 966 | if (s/$apachetime$zone()/$1 /i || | |||
| 967 | s/$apachetime$zone2?/$1 /i || | |||
| 968 | s/(^|[^a-z])$at\s*$D$mnsec$zone()/$1 /i || | |||
| 969 | s/(^|[^a-z])$at\s*$D$mnsec$zone2?/$1 /i || | |||
| 970 | s/(^|[^0-9])(\d)$mnsec$zone()/$1 /i || | |||
| 971 | s/(^|[^0-9])(\d)$mnsec$zone2?/$1 /i || | |||
| 972 | (s/(t)$D$mnsec$zone()/$1 /i and (($iso=$tmp) || 1)) || | |||
| 973 | (s/(t)$D$mnsec$zone2?/$1 /i and (($iso=$tmp) || 1)) || | |||
| 974 | (s/()$DD$mnsec$zone()/ /i and (($iso=$tmp) || 1)) || | |||
| 975 | (s/()$DD$mnsec$zone2?/ /i and (($iso=$tmp) || 1)) || | |||
| 976 | s/(^|$at\s*|\s+)$D()()\s*$ampmexp$zone()/ /i || | |||
| 977 | s/(^|$at\s*|\s+)$D()()\s*$ampmexp$zone2?/ /i || | |||
| 978 | 0 | |||
| 979 | ) { | |||
| 980 | ($h,$mn,$s,$ampm,$z,$z2)=($2,$3,$4,$5,$6,$7); | |||
| 981 | if (defined ($z)) { | |||
| 982 | if ($z =~ /^[+-]\d{2}:\d{2}$/) { | |||
| 983 | $z=~ s/://; | |||
| 984 | } elsif ($z =~ /^[+-]\d{2}$/) { | |||
| 985 | $z .= "00"; | |||
| 986 | } | |||
| 987 | } | |||
| 988 | $time=1; | |||
| 989 | _Date_TimeCheck(\$h,\$mn,\$s,\$ampm); | |||
| 990 | $y=$m=$d=""; | |||
| 991 | # We're going to be calling TimeCheck again below (when we check the | |||
| 992 | # final date), so get rid of $ampm so that we don't have an error | |||
| 993 | # due to "15:30:00 PM". It'll get reset below. | |||
| 994 | $ampm=""; | |||
| 995 | if (/^\s*$/) { | |||
| 996 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 997 | last PARSE; | |||
| 998 | } | |||
| 999 | } | |||
| 1000 | } | |||
| 1001 | $time=0 if ($time ne "1"); | |||
| 1002 | s/\s+$//; | |||
| 1003 | s/^\s+//; | |||
| 1004 | ||||
| 1005 | # if a zone was found, get rid of the regexps | |||
| 1006 | if ($z) { | |||
| 1007 | $zone=""; | |||
| 1008 | $zone2=""; | |||
| 1009 | } | |||
| 1010 | ||||
| 1011 | # dateTtime ISO 8601 formats | |||
| 1012 | my($orig)=$_; | |||
| 1013 | ||||
| 1014 | # Parse ISO 8601 dates now (which may still have a zone stuck to it). | |||
| 1015 | if ( ($iso && /^([0-9-]+(?:W[0-9-]+)?)$zone?$/i) || | |||
| 1016 | ($iso && /^([0-9-]+(?:W[0-9-]+)?)$zone2?$/i) || | |||
| 1017 | ($iso && /^([0-9-]+(?:T[0-9-]+)?)$zone?$/i) || | |||
| 1018 | ($iso && /^([0-9-]+(?:T[0-9-]+)?)$zone2?$/i) || | |||
| 1019 | ($iso && /^([0-9-]+)T$zone?$/i) || | |||
| 1020 | ($iso && /^([0-9-]+)T$zone2?$/i) || | |||
| 1021 | 0) { | |||
| 1022 | ||||
| 1023 | # If we already got a timezone, don't get another one. | |||
| 1024 | my(@z); | |||
| 1025 | if ($z) { | |||
| 1026 | @z=($z,$z2); | |||
| 1027 | $z=""; | |||
| 1028 | } | |||
| 1029 | ($_,$z,$z2) = ($1,$2,$3); | |||
| 1030 | ($z,$z2)=@z if (@z); | |||
| 1031 | ||||
| 1032 | s,([0-9])\s*-,$1 ,g; # Change all ISO8601 seps to spaces | |||
| 1033 | s/^\s+//; | |||
| 1034 | s/\s+$//; | |||
| 1035 | ||||
| 1036 | if (/^$D4\s*$DD\s*$DD\s*t?$DD(?:$DD(?:$DD(\d*))?)?$/i || | |||
| 1037 | /^$DD\s+$DD\s*$DD\s*t?$DD(?:$DD(?:$DD(\d*))?)?$/i || | |||
| 1038 | 0 | |||
| 1039 | ) { | |||
| 1040 | # ISO 8601 Dates with times | |||
| 1041 | # YYYYMMDDtHHMNSSFFFF... | |||
| 1042 | # YYYYMMDDtHHMNSS | |||
| 1043 | # YYYYMMDDtHHMN | |||
| 1044 | # YYYYMMDDtHH | |||
| 1045 | # YY MMDDtHHMNSSFFFF... | |||
| 1046 | # YY MMDDtHHMNSS | |||
| 1047 | # YY MMDDtHHMN | |||
| 1048 | # YY MMDDtHH | |||
| 1049 | # The t is an optional letter "t". | |||
| 1050 | ($y,$m,$d,$h,$mn,$s,$tmp)=($1,$2,$3,$4,$5,$6,$7); | |||
| 1051 | if ($h==24 && (! defined $mn || $mn==0) && (! defined $s || $s==0)) { | |||
| 1052 | $h=0; | |||
| 1053 | $midnight=1; | |||
| 1054 | } | |||
| 1055 | $z = "" if (! defined $h); | |||
| 1056 | return "" if ($time && defined $h); | |||
| 1057 | last PARSE; | |||
| 1058 | ||||
| 1059 | } elsif (/^$D4(?:\s*$DD(?:\s*$DD)?)?$/ || | |||
| 1060 | /^$DD(?:\s+$DD(?:\s*$DD)?)?$/) { | |||
| 1061 | # ISO 8601 Dates | |||
| 1062 | # YYYYMMDD | |||
| 1063 | # YYYYMM | |||
| 1064 | # YYYY | |||
| 1065 | # YY MMDD | |||
| 1066 | # YY MM | |||
| 1067 | # YY | |||
| 1068 | ($y,$m,$d)=($1,$2,$3); | |||
| 1069 | last PARSE; | |||
| 1070 | ||||
| 1071 | } elsif (/^$YY\s+$D\s+$D/) { | |||
| 1072 | # YY-M-D | |||
| 1073 | ($y,$m,$d)=($1,$2,$3); | |||
| 1074 | last PARSE; | |||
| 1075 | ||||
| 1076 | } elsif (/^$YY\s*W$DD\s*(\d)?$/i) { | |||
| 1077 | # YY-W##-D | |||
| 1078 | ($y,$wofm,$dofw)=($1,$2,$3); | |||
| 1079 | ($y,$m,$d)=_Date_NthWeekOfYear($y,$wofm,$dofw); | |||
| 1080 | last PARSE; | |||
| 1081 | ||||
| 1082 | } elsif (/^$D4\s*(\d{3})$/ || | |||
| 1083 | /^$DD\s*(\d{3})$/) { | |||
| 1084 | # YYDOY | |||
| 1085 | ($y,$which)=($1,$2); | |||
| 1086 | ($y,$m,$d)=Date_NthDayOfYear($y,$which); | |||
| 1087 | last PARSE; | |||
| 1088 | ||||
| 1089 | } elsif ($iso<0) { | |||
| 1090 | # We confused something like 1999/August12:00:00 | |||
| 1091 | # with a dateTtime format | |||
| 1092 | $_=$orig; | |||
| 1093 | ||||
| 1094 | } else { | |||
| 1095 | return ""; | |||
| 1096 | } | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | # All deltas that are not ISO-8601 dates are NOT dates. | |||
| 1100 | return "" if ($Curr{"InCalc"} && $delta); | |||
| 1101 | if ($delta) { | |||
| 1102 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1103 | return _DateCalc_DateDelta($Curr{"Now"},$delta); | |||
| 1104 | } | |||
| 1105 | ||||
| 1106 | # Check for some special types of dates (next, prev) | |||
| 1107 | foreach $from (keys %{ $Lang{$L}{"Repl"} }) { | |||
| 1108 | $to=$Lang{$L}{"Repl"}{$from}; | |||
| 1109 | s/(^|[^a-z])$from($|[^a-z])/$1$to$2/i; | |||
| 1110 | } | |||
| 1111 | if (/$wom/i || /$future/i || /$later/i || /$past/i || | |||
| 1112 | /$next/i || /$prev/i || /^$week$/i || /$wkabb/i) { | |||
| 1113 | $tmp=0; | |||
| 1114 | ||||
| 1115 | if (/^$wom\s*$week$of\s*$month\s*$YY?$/i) { | |||
| 1116 | # last friday in October 95 | |||
| 1117 | ($wofm,$dofw,$m,$y)=($1,$2,$3,$4); | |||
| 1118 | # fix $m, $y | |||
| 1119 | return "" if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 1120 | $dofw=$week{lc($dofw)}; | |||
| 1121 | $wofm=$wom{lc($wofm)}; | |||
| 1122 | # Get the first day of the month | |||
| 1123 | $date=_Date_Join($y,$m,1,$h,$mn,$s); | |||
| 1124 | if ($wofm==-1) { | |||
| 1125 | $date=_DateCalc_DateDelta($date,"+0:1:0:0:0:0:0",\$err,0); | |||
| 1126 | $date=Date_GetPrev($date,$dofw,0); | |||
| 1127 | } else { | |||
| 1128 | for ($i=0; $i<$wofm; $i++) { | |||
| 1129 | if ($i==0) { | |||
| 1130 | $date=Date_GetNext($date,$dofw,1); | |||
| 1131 | } else { | |||
| 1132 | $date=Date_GetNext($date,$dofw,0); | |||
| 1133 | } | |||
| 1134 | } | |||
| 1135 | } | |||
| 1136 | last PARSE; | |||
| 1137 | ||||
| 1138 | } elsif (/^$last$day$of\s*$month(?:$of?\s*$YY)?/i) { | |||
| 1139 | # last day in month | |||
| 1140 | ($m,$y)=($1,$2); | |||
| 1141 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1142 | $y=_Date_FixYear($y) if (! defined $y or length($y)<4); | |||
| 1143 | $m=$month{lc($m)}; | |||
| 1144 | $d=Date_DaysInMonth($m,$y); | |||
| 1145 | last PARSE; | |||
| 1146 | ||||
| 1147 | } elsif (/^$week$/i) { | |||
| 1148 | # friday | |||
| 1149 | ($dofw)=($1); | |||
| 1150 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1151 | $date=Date_GetPrev($Curr{"Now"},$Cnf{"FirstDay"},1); | |||
| 1152 | $date=Date_GetNext($date,$dofw,1,$h,$mn,$s); | |||
| 1153 | last PARSE; | |||
| 1154 | ||||
| 1155 | } elsif (/^$next\s*$week$/i) { | |||
| 1156 | # next friday | |||
| 1157 | ($dofw)=($1); | |||
| 1158 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1159 | $date=Date_GetNext($Curr{"Now"},$dofw,0,$h,$mn,$s); | |||
| 1160 | last PARSE; | |||
| 1161 | ||||
| 1162 | } elsif (/^$prev\s*$week$/i) { | |||
| 1163 | # last friday | |||
| 1164 | ($dofw)=($1); | |||
| 1165 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1166 | $date=Date_GetPrev($Curr{"Now"},$dofw,0,$h,$mn,$s); | |||
| 1167 | last PARSE; | |||
| 1168 | ||||
| 1169 | } elsif (/^$next$wkabb$/i) { | |||
| 1170 | # next week | |||
| 1171 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1172 | $date=_DateCalc_DateDelta($Curr{"Now"},"+0:0:1:0:0:0:0",\$err,0); | |||
| 1173 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1174 | last PARSE; | |||
| 1175 | } elsif (/^$prev$wkabb$/i) { | |||
| 1176 | # last week | |||
| 1177 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1178 | $date=_DateCalc_DateDelta($Curr{"Now"},"-0:0:1:0:0:0:0",\$err,0); | |||
| 1179 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1180 | last PARSE; | |||
| 1181 | ||||
| 1182 | } elsif (/^$next$mabb$/i) { | |||
| 1183 | # next month | |||
| 1184 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1185 | $date=_DateCalc_DateDelta($Curr{"Now"},"+0:1:0:0:0:0:0",\$err,0); | |||
| 1186 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1187 | last PARSE; | |||
| 1188 | } elsif (/^$prev$mabb$/i) { | |||
| 1189 | # last month | |||
| 1190 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1191 | $date=_DateCalc_DateDelta($Curr{"Now"},"-0:1:0:0:0:0:0",\$err,0); | |||
| 1192 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1193 | last PARSE; | |||
| 1194 | ||||
| 1195 | } elsif (/^$future\s*(\d+)$day$/i || | |||
| 1196 | /^(\d+)$day$later$/i) { | |||
| 1197 | # in 2 days | |||
| 1198 | # 2 days later | |||
| 1199 | ($num)=($1); | |||
| 1200 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1201 | $date=_DateCalc_DateDelta($Curr{"Now"},"+0:0:0:$num:0:0:0", | |||
| 1202 | \$err,0); | |||
| 1203 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1204 | last PARSE; | |||
| 1205 | } elsif (/^(\d+)$day$past$/i) { | |||
| 1206 | # 2 days ago | |||
| 1207 | ($num)=($1); | |||
| 1208 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1209 | $date=_DateCalc_DateDelta($Curr{"Now"},"-0:0:0:$num:0:0:0", | |||
| 1210 | \$err,0); | |||
| 1211 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1212 | last PARSE; | |||
| 1213 | ||||
| 1214 | } elsif (/^$future\s*(\d+)$wkabb$/i || | |||
| 1215 | /^(\d+)$wkabb$later$/i) { | |||
| 1216 | # in 2 weeks | |||
| 1217 | # 2 weeks later | |||
| 1218 | ($num)=($1); | |||
| 1219 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1220 | $date=_DateCalc_DateDelta($Curr{"Now"},"+0:0:$num:0:0:0:0", | |||
| 1221 | \$err,0); | |||
| 1222 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1223 | last PARSE; | |||
| 1224 | } elsif (/^(\d+)$wkabb$past$/i) { | |||
| 1225 | # 2 weeks ago | |||
| 1226 | ($num)=($1); | |||
| 1227 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1228 | $date=_DateCalc_DateDelta($Curr{"Now"},"-0:0:$num:0:0:0:0", | |||
| 1229 | \$err,0); | |||
| 1230 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1231 | last PARSE; | |||
| 1232 | ||||
| 1233 | } elsif (/^$future\s*(\d+)$mabb$/i || | |||
| 1234 | /^(\d+)$mabb$later$/i) { | |||
| 1235 | # in 2 months | |||
| 1236 | # 2 months later | |||
| 1237 | ($num)=($1); | |||
| 1238 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1239 | $date=_DateCalc_DateDelta($Curr{"Now"},"+0:$num:0:0:0:0:0", | |||
| 1240 | \$err,0); | |||
| 1241 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1242 | last PARSE; | |||
| 1243 | } elsif (/^(\d+)$mabb$past$/i) { | |||
| 1244 | # 2 months ago | |||
| 1245 | ($num)=($1); | |||
| 1246 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1247 | $date=_DateCalc_DateDelta($Curr{"Now"},"-0:$num:0:0:0:0:0", | |||
| 1248 | \$err,0); | |||
| 1249 | $date=Date_SetTime($date,$h,$mn,$s) if (defined $h); | |||
| 1250 | last PARSE; | |||
| 1251 | ||||
| 1252 | } elsif (/^$week$future\s*(\d+)$wkabb$/i || | |||
| 1253 | /^$week\s*(\d+)$wkabb$later$/i) { | |||
| 1254 | # friday in 2 weeks | |||
| 1255 | # friday 2 weeks later | |||
| 1256 | ($dofw,$num)=($1,$2); | |||
| 1257 | $tmp="+"; | |||
| 1258 | } elsif (/^$week\s*(\d+)$wkabb$past$/i) { | |||
| 1259 | # friday 2 weeks ago | |||
| 1260 | ($dofw,$num)=($1,$2); | |||
| 1261 | $tmp="-"; | |||
| 1262 | } elsif (/^$future\s*(\d+)$wkabb$on$week$/i || | |||
| 1263 | /^(\d+)$wkabb$later$on$week$/i) { | |||
| 1264 | # in 2 weeks on friday | |||
| 1265 | # 2 weeks later on friday | |||
| 1266 | ($num,$dofw)=($1,$2); | |||
| 1267 | $tmp="+" | |||
| 1268 | } elsif (/^(\d+)$wkabb$past$on$week$/i) { | |||
| 1269 | # 2 weeks ago on friday | |||
| 1270 | ($num,$dofw)=($1,$2); | |||
| 1271 | $tmp="-"; | |||
| 1272 | } elsif (/^$week\s*$wkabb$/i) { | |||
| 1273 | # monday week (British date: in 1 week on monday) | |||
| 1274 | $dofw=$1; | |||
| 1275 | $num=1; | |||
| 1276 | $tmp="+"; | |||
| 1277 | } elsif ( (/^$now\s*$wkabb$/i && ($tmp="Now")) || | |||
| 1278 | (/^$today\s*$wkabb$/i && ($tmp="Today")) ) { | |||
| 1279 | # now week (British date: 1 week from now) | |||
| 1280 | # today week (British date: 1 week from today) | |||
| 1281 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1282 | $date=_DateCalc_DateDelta($Curr{$tmp},"+0:0:1:0:0:0:0",\$err,0); | |||
| 1283 | $date=Date_SetTime($date,$h,$mn,$s) if ($time); | |||
| 1284 | last PARSE; | |||
| 1285 | } elsif (/^$offset\s*$wkabb$/i) { | |||
| 1286 | # tomorrow week (British date: 1 week from tomorrow) | |||
| 1287 | ($offset)=($1); | |||
| 1288 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1289 | $offset=$Lang{$L}{"OffsetH"}{lc($offset)}; | |||
| 1290 | $date=_DateCalc_DateDelta($Curr{"Now"},$offset,\$err,0); | |||
| 1291 | $date=_DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0); | |||
| 1292 | if ($time) { | |||
| 1293 | return "" | |||
| 1294 | if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 1295 | $date=Date_SetTime($date,$h,$mn,$s); | |||
| 1296 | } | |||
| 1297 | last PARSE; | |||
| 1298 | } | |||
| 1299 | ||||
| 1300 | if ($tmp) { | |||
| 1301 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1302 | $date=_DateCalc_DateDelta($Curr{"Now"}, | |||
| 1303 | $tmp . "0:0:$num:0:0:0:0",\$err,0); | |||
| 1304 | $date=Date_GetPrev($date,$Cnf{"FirstDay"},1); | |||
| 1305 | $date=Date_GetNext($date,$dofw,1,$h,$mn,$s); | |||
| 1306 | last PARSE; | |||
| 1307 | } | |||
| 1308 | } | |||
| 1309 | ||||
| 1310 | # Change (2nd, second) to 2 | |||
| 1311 | $tmp=0; | |||
| 1312 | if (/(^|[^a-z0-9])$dom($|[^a-z0-9])/i) { | |||
| 1313 | if (/^\s*$dom\s*$/) { | |||
| 1314 | ($d)=($1); | |||
| 1315 | $d=$dom{lc($d)}; | |||
| 1316 | $m=$Curr{"M"}; | |||
| 1317 | last PARSE; | |||
| 1318 | } | |||
| 1319 | my $from = $2; | |||
| 1320 | my $to = $dom{ lc($from) }; | |||
| 1321 | s/(^|[^a-z])$from($|[^a-z])/$1 $to $2/i; | |||
| 1322 | s/^\s+//; | |||
| 1323 | s/\s+$//; | |||
| 1324 | } | |||
| 1325 | ||||
| 1326 | # Another set of special dates (Nth week) | |||
| 1327 | if (/^$D\s*$week(?:$of?\s*$YY)?$/i) { | |||
| 1328 | # 22nd sunday in 1996 | |||
| 1329 | ($which,$dofw,$y)=($1,$2,$3); | |||
| 1330 | $y=$Curr{"Y"} if (! $y); | |||
| 1331 | $y--; # previous year | |||
| 1332 | $tmp=Date_GetNext("$y-12-31",$dofw,0); | |||
| 1333 | if ($which>1) { | |||
| 1334 | $tmp=_DateCalc_DateDelta($tmp,"+0:0:".($which-1).":0:0:0:0",\$err,0); | |||
| 1335 | } | |||
| 1336 | ($y,$m,$d)=(_Date_Split($tmp, 1))[0..2]; | |||
| 1337 | last PARSE; | |||
| 1338 | } elsif (/^$week$wkabb\s*$D(?:$of?\s*$YY)?$/i || | |||
| 1339 | /^$week\s*$D$wkabb(?:$of?\s*$YY)?$/i) { | |||
| 1340 | # sunday week 22 in 1996 | |||
| 1341 | # sunday 22nd week in 1996 | |||
| 1342 | ($dofw,$which,$y)=($1,$2,$3); | |||
| 1343 | ($y,$m,$d)=_Date_NthWeekOfYear($y,$which,$dofw); | |||
| 1344 | last PARSE; | |||
| 1345 | } | |||
| 1346 | ||||
| 1347 | # Get rid of day of week | |||
| 1348 | if (/(^|[^a-z])$week($|[^a-z])/i) { | |||
| 1349 | $wk=$2; | |||
| 1350 | (s/(^|[^a-z])$week,/$1 /i) || | |||
| 1351 | s/(^|[^a-z])$week($|[^a-z])/$1 $3/i; | |||
| 1352 | s/^\s+//; | |||
| 1353 | s/\s+$//; | |||
| 1354 | } | |||
| 1355 | ||||
| 1356 | { | |||
| 1357 | # So that we can handle negative epoch times, let's convert | |||
| 1358 | # things like "epoch -" to "epochNEGATIVE " before we strip out | |||
| 1359 | # the $sep chars, which include '-'. | |||
| 1360 | s,epoch\s*-,epochNEGATIVE ,g; | |||
| 1361 | ||||
| 1362 | # Non-ISO8601 dates | |||
| 1363 | s,\s*$sep\s*, ,g; # change all non-ISO8601 seps to spaces | |||
| 1364 | s,^\s*,,; # remove leading/trailing space | |||
| 1365 | s,\s*$,,; | |||
| 1366 | ||||
| 1367 | if (/^$D\s+$D(?:\s+$YY)?$/) { | |||
| 1368 | # MM DD YY (DD MM YY non-US) | |||
| 1369 | ($m,$d,$y)=($1,$2,$3); | |||
| 1370 | ($m,$d)=($d,$m) if ($type ne "US"); | |||
| 1371 | last PARSE; | |||
| 1372 | ||||
| 1373 | } elsif (/^$D4\s*$D\s*$D$/) { | |||
| 1374 | # YYYY MM DD | |||
| 1375 | ($y,$m,$d)=($1,$2,$3); | |||
| 1376 | last PARSE; | |||
| 1377 | ||||
| 1378 | } elsif (s/(^|[^a-z])$month($|[^a-z])/$1 $3/i) { | |||
| 1379 | ($m)=($2); | |||
| 1380 | ||||
| 1381 | if (/^\s*$D(?:\s+$YY)?\s*$/) { | |||
| 1382 | # mmm DD YY | |||
| 1383 | # DD mmm YY | |||
| 1384 | # DD YY mmm | |||
| 1385 | ($d,$y)=($1,$2); | |||
| 1386 | last PARSE; | |||
| 1387 | ||||
| 1388 | } elsif (/^\s*$D$D4\s*$/) { | |||
| 1389 | # mmm DD YYYY | |||
| 1390 | # DD mmm YYYY | |||
| 1391 | # DD YYYY mmm | |||
| 1392 | ($d,$y)=($1,$2); | |||
| 1393 | last PARSE; | |||
| 1394 | ||||
| 1395 | } elsif (/^\s*$D4\s*$D\s*$/) { | |||
| 1396 | # mmm YYYY DD | |||
| 1397 | # YYYY mmm DD | |||
| 1398 | # YYYY DD mmm | |||
| 1399 | ($y,$d)=($1,$2); | |||
| 1400 | last PARSE; | |||
| 1401 | ||||
| 1402 | } elsif (/^\s*$D4\s*$/) { | |||
| 1403 | # mmm YYYY | |||
| 1404 | # YYYY mmm | |||
| 1405 | ($y,$d)=($1,1); | |||
| 1406 | last PARSE; | |||
| 1407 | ||||
| 1408 | } else { | |||
| 1409 | return ""; | |||
| 1410 | } | |||
| 1411 | ||||
| 1412 | } elsif (/^epochNEGATIVE (\d+)$/) { | |||
| 1413 | $s=$1; | |||
| 1414 | $date=DateCalc("1970-01-01 00:00 GMT","-0:0:$s"); | |||
| 1415 | } elsif (/^epoch\s*(\d+)$/i) { | |||
| 1416 | $s=$1; | |||
| 1417 | $date=DateCalc("1970-01-01 00:00 GMT","+0:0:$s"); | |||
| 1418 | ||||
| 1419 | } elsif ( (/^$now$/i && ($tmp="Now")) || | |||
| 1420 | (/^$today$/i && ($tmp="Today")) ) { | |||
| 1421 | # now, today | |||
| 1422 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1423 | $date=$Curr{$tmp}; | |||
| 1424 | if ($time) { | |||
| 1425 | return "" | |||
| 1426 | if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 1427 | $date=Date_SetTime($date,$h,$mn,$s); | |||
| 1428 | } | |||
| 1429 | last PARSE; | |||
| 1430 | ||||
| 1431 | } elsif (/^$offset$/i) { | |||
| 1432 | # yesterday, tomorrow | |||
| 1433 | ($offset)=($1); | |||
| 1434 | Date_Init() if (! $Cnf{"UpdateCurrTZ"}); | |||
| 1435 | $offset=$Lang{$L}{"OffsetH"}{lc($offset)}; | |||
| 1436 | $date=_DateCalc_DateDelta($Curr{"Now"},$offset,\$err,0); | |||
| 1437 | if ($time) { | |||
| 1438 | return "" | |||
| 1439 | if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 1440 | $date=Date_SetTime($date,$h,$mn,$s); | |||
| 1441 | } | |||
| 1442 | last PARSE; | |||
| 1443 | ||||
| 1444 | } else { | |||
| 1445 | return ""; | |||
| 1446 | } | |||
| 1447 | } | |||
| 1448 | } | |||
| 1449 | ||||
| 1450 | if (! $date) { | |||
| 1451 | return "" if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 1452 | $date=_Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 1453 | } | |||
| 1454 | $date=Date_ConvTZ($date,$z); | |||
| 1455 | if ($midnight) { | |||
| 1456 | $date=_DateCalc_DateDelta($date,"+0:0:0:1:0:0:0"); | |||
| 1457 | } | |||
| 1458 | return $date; | |||
| 1459 | } | |||
| 1460 | ||||
| 1461 | sub ParseDate { | |||
| 1462 | print "DEBUG: ParseDate\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 1463 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 1464 | my($args,@args,@a,$ref,$date)=(); | |||
| 1465 | @a=@_; | |||
| 1466 | ||||
| 1467 | # @a : is the list of args to ParseDate. Currently, only one argument | |||
| 1468 | # is allowed and it must be a scalar (or a reference to a scalar) | |||
| 1469 | # or a reference to an array. | |||
| 1470 | ||||
| 1471 | if ($#a!=0) { | |||
| 1472 | print "ERROR: Invalid number of arguments to ParseDate.\n"; | |||
| 1473 | return ""; | |||
| 1474 | } | |||
| 1475 | $args=$a[0]; | |||
| 1476 | $ref=ref $args; | |||
| 1477 | if (! $ref) { | |||
| 1478 | return $args if (_Date_Split($args)); | |||
| 1479 | @args=($args); | |||
| 1480 | } elsif ($ref eq "ARRAY") { | |||
| 1481 | @args=@$args; | |||
| 1482 | } elsif ($ref eq "SCALAR") { | |||
| 1483 | return $$args if (_Date_Split($$args)); | |||
| 1484 | @args=($$args); | |||
| 1485 | } else { | |||
| 1486 | print "ERROR: Invalid arguments to ParseDate.\n"; | |||
| 1487 | return ""; | |||
| 1488 | } | |||
| 1489 | @a=@args; | |||
| 1490 | ||||
| 1491 | # @args : a list containing all the arguments (dereferenced if appropriate) | |||
| 1492 | # @a : a list containing all the arguments currently being examined | |||
| 1493 | # $ref : nil, "SCALAR", or "ARRAY" depending on whether a scalar, a | |||
| 1494 | # reference to a scalar, or a reference to an array was passed in | |||
| 1495 | # $args : the scalar or refererence passed in | |||
| 1496 | ||||
| 1497 | PARSE: while($#a>=0) { | |||
| 1498 | $date=join(" ",@a); | |||
| 1499 | $date=ParseDateString($date); | |||
| 1500 | last if ($date); | |||
| 1501 | pop(@a); | |||
| 1502 | } # PARSE | |||
| 1503 | ||||
| 1504 | splice(@args,0,$#a + 1); | |||
| 1505 | @$args= @args if (defined $ref and $ref eq "ARRAY"); | |||
| 1506 | $date; | |||
| 1507 | } | |||
| 1508 | ||||
| 1509 | sub Date_Cmp { | |||
| 1510 | my($D1,$D2)=@_; | |||
| 1511 | my($date1)=ParseDateString($D1); | |||
| 1512 | my($date2)=ParseDateString($D2); | |||
| 1513 | return $date1 cmp $date2; | |||
| 1514 | } | |||
| 1515 | ||||
| 1516 | # **NOTE** | |||
| 1517 | # The calc routines all call parse routines, so it is never necessary to | |||
| 1518 | # call Date_Init in the calc routines. | |||
| 1519 | sub DateCalc { | |||
| 1520 | print "DEBUG: DateCalc\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 1521 | my($D1,$D2,@arg)=@_; | |||
| 1522 | my($ref,$err,$errref,$mode)=(); | |||
| 1523 | ||||
| 1524 | ($errref,$mode) = (@arg); | |||
| 1525 | $ref=0; | |||
| 1526 | ||||
| 1527 | if (defined $errref) { | |||
| 1528 | if (ref $errref) { | |||
| 1529 | $ref=1; | |||
| 1530 | } elsif (! defined $mode) { | |||
| 1531 | $mode=$errref; | |||
| 1532 | $errref=""; | |||
| 1533 | } | |||
| 1534 | } | |||
| 1535 | ||||
| 1536 | my(@date,@delta,$ret,$tmp,$oldincalc,$oldmode)=(); | |||
| 1537 | ||||
| 1538 | if (exists $Curr{"Mode"}) { | |||
| 1539 | $oldmode = $Curr{"Mode"}; | |||
| 1540 | } else { | |||
| 1541 | $oldmode = 0; | |||
| 1542 | } | |||
| 1543 | ||||
| 1544 | if (defined $mode and $mode>=0 and $mode<=3) { | |||
| 1545 | $Curr{"Mode"}=$mode; | |||
| 1546 | } else { | |||
| 1547 | $Curr{"Mode"}=0; | |||
| 1548 | } | |||
| 1549 | ||||
| 1550 | if (exists $Curr{"InCalc"}) { | |||
| 1551 | $oldincalc = $Curr{"InCalc"}; | |||
| 1552 | } else { | |||
| 1553 | $oldincalc = 0; | |||
| 1554 | } | |||
| 1555 | $Curr{"InCalc"}=1; | |||
| 1556 | ||||
| 1557 | if ($tmp=ParseDateString($D1)) { | |||
| 1558 | # If we've already parsed the date, we don't want to do it a second | |||
| 1559 | # time (so we don't convert timezones twice). | |||
| 1560 | if (_Date_Split($D1)) { | |||
| 1561 | push(@date,$D1); | |||
| 1562 | } else { | |||
| 1563 | push(@date,$tmp); | |||
| 1564 | } | |||
| 1565 | } elsif ($tmp=ParseDateDelta($D1)) { | |||
| 1566 | push(@delta,$tmp); | |||
| 1567 | } else { | |||
| 1568 | $$errref=1 if ($ref); | |||
| 1569 | $Curr{"InCalc"} = $oldincalc; | |||
| 1570 | $Curr{"Mode"} = $oldmode; | |||
| 1571 | return; | |||
| 1572 | } | |||
| 1573 | ||||
| 1574 | if ($tmp=ParseDateString($D2)) { | |||
| 1575 | if (_Date_Split($D2)) { | |||
| 1576 | push(@date,$D2); | |||
| 1577 | } else { | |||
| 1578 | push(@date,$tmp); | |||
| 1579 | } | |||
| 1580 | } elsif ($tmp=ParseDateDelta($D2)) { | |||
| 1581 | push(@delta,$tmp); | |||
| 1582 | $mode = $Curr{"Mode"}; | |||
| 1583 | } else { | |||
| 1584 | $$errref=2 if ($ref); | |||
| 1585 | $Curr{"InCalc"} = $oldincalc; | |||
| 1586 | $Curr{"Mode"} = $oldmode; | |||
| 1587 | return; | |||
| 1588 | } | |||
| 1589 | ||||
| 1590 | $Curr{"InCalc"} = $oldincalc; | |||
| 1591 | $Curr{"Mode"} = $oldmode; | |||
| 1592 | ||||
| 1593 | if ($#date==1) { | |||
| 1594 | $ret=_DateCalc_DateDate(@date,$mode); | |||
| 1595 | } elsif ($#date==0) { | |||
| 1596 | $ret=_DateCalc_DateDelta(@date,@delta,\$err,$mode); | |||
| 1597 | $$errref=$err if ($ref); | |||
| 1598 | } else { | |||
| 1599 | $ret=_DateCalc_DeltaDelta(@delta,$mode); | |||
| 1600 | } | |||
| 1601 | $ret; | |||
| 1602 | } | |||
| 1603 | ||||
| 1604 | sub ParseDateDelta { | |||
| 1605 | print "DEBUG: ParseDateDelta\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 1606 | my($args,@args,@a,$ref)=(); | |||
| 1607 | local($_)=(); | |||
| 1608 | @a=@_; | |||
| 1609 | ||||
| 1610 | # @a : is the list of args to ParseDateDelta. Currently, only one argument | |||
| 1611 | # is allowed and it must be a scalar (or a reference to a scalar) | |||
| 1612 | # or a reference to an array. | |||
| 1613 | ||||
| 1614 | if ($#a!=0) { | |||
| 1615 | print "ERROR: Invalid number of arguments to ParseDateDelta.\n"; | |||
| 1616 | return ""; | |||
| 1617 | } | |||
| 1618 | $args=$a[0]; | |||
| 1619 | $ref=ref $args; | |||
| 1620 | if (! $ref) { | |||
| 1621 | @args=($args); | |||
| 1622 | } elsif ($ref eq "ARRAY") { | |||
| 1623 | @args=@$args; | |||
| 1624 | } elsif ($ref eq "SCALAR") { | |||
| 1625 | @args=($$args); | |||
| 1626 | } else { | |||
| 1627 | print "ERROR: Invalid arguments to ParseDateDelta.\n"; | |||
| 1628 | return ""; | |||
| 1629 | } | |||
| 1630 | @a=@args; | |||
| 1631 | ||||
| 1632 | # @args : a list containing all the arguments (dereferenced if appropriate) | |||
| 1633 | # @a : a list containing all the arguments currently being examined | |||
| 1634 | # $ref : nil, "SCALAR", or "ARRAY" depending on whether a scalar, a | |||
| 1635 | # reference to a scalar, or a reference to an array was passed in | |||
| 1636 | # $args : the scalar or refererence passed in | |||
| 1637 | ||||
| 1638 | my(@colon,@delta,$delta,$dir,$colon,$sign,$val)=(); | |||
| 1639 | my($len,$tmp,$tmp2,$tmpl)=(); | |||
| 1640 | my($from,$to)=(); | |||
| 1641 | my($workweek)=$Cnf{"WorkWeekEnd"}-$Cnf{"WorkWeekBeg"}+1; | |||
| 1642 | ||||
| 1643 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 1644 | # A sign can be a sequence of zero or more + and - signs, this | |||
| 1645 | # allows for deltas like '+ -2 days'. | |||
| 1646 | my($signexp)='((?:[+-]\s*)*)'; | |||
| 1647 | my($numexp)='(\d+)'; | |||
| 1648 | my($exp1)="(?: \\s* $signexp \\s* $numexp \\s*)"; | |||
| 1649 | my($yexp,$mexp,$wexp,$dexp,$hexp,$mnexp,$sexp,$i)=(); | |||
| 1650 | $yexp=$mexp=$wexp=$dexp=$hexp=$mnexp=$sexp="()()"; | |||
| 1651 | $yexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Yabb"} .")?"; | |||
| 1652 | $mexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Mabb"} .")?"; | |||
| 1653 | $wexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Wabb"} .")?"; | |||
| 1654 | $dexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Dabb"} .")?"; | |||
| 1655 | $hexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Habb"} .")?"; | |||
| 1656 | $mnexp="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"MNabb"}.")?"; | |||
| 1657 | $sexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Sabb"} ."?)?"; | |||
| 1658 | my($future)=$Lang{$Cnf{"Language"}}{"Future"}; | |||
| 1659 | my($later)=$Lang{$Cnf{"Language"}}{"Later"}; | |||
| 1660 | my($past)=$Lang{$Cnf{"Language"}}{"Past"}; | |||
| 1661 | ||||
| 1662 | $delta=""; | |||
| 1663 | PARSE: while (@a) { | |||
| 1664 | $_ = join(" ", grep {defined;} @a); | |||
| 1665 | s/\s+$//; | |||
| 1666 | last if ($_ eq ""); | |||
| 1667 | ||||
| 1668 | # Mode is set in DateCalc. ParseDateDelta only overrides it if the | |||
| 1669 | # string contains a mode. | |||
| 1670 | if ($Lang{$Cnf{"Language"}}{"Exact"} && | |||
| 1671 | s/$Lang{$Cnf{"Language"}}{"Exact"}//) { | |||
| 1672 | $Curr{"Mode"}=0; | |||
| 1673 | } elsif ($Lang{$Cnf{"Language"}}{"Approx"} && | |||
| 1674 | s/$Lang{$Cnf{"Language"}}{"Approx"}//) { | |||
| 1675 | $Curr{"Mode"}=1; | |||
| 1676 | } elsif ($Lang{$Cnf{"Language"}}{"Business"} && | |||
| 1677 | s/$Lang{$Cnf{"Language"}}{"Business"}//) { | |||
| 1678 | $Curr{"Mode"}=2; | |||
| 1679 | } elsif (! exists $Curr{"Mode"}) { | |||
| 1680 | $Curr{"Mode"}=0; | |||
| 1681 | } | |||
| 1682 | $workweek=7 if ($Curr{"Mode"} != 2); | |||
| 1683 | ||||
| 1684 | foreach $from (keys %{ $Lang{$Cnf{"Language"}}{"Repl"} }) { | |||
| 1685 | $to=$Lang{$Cnf{"Language"}}{"Repl"}{$from}; | |||
| 1686 | s/(^|[^a-z])$from($|[^a-z])/$1$to$2/i; | |||
| 1687 | } | |||
| 1688 | ||||
| 1689 | # in or ago | |||
| 1690 | # | |||
| 1691 | # We need to make sure that $later, $future, and $past don't contain each | |||
| 1692 | # other... Romanian pointed this out where $past is "in urma" and $future | |||
| 1693 | # is "in". When they do, we have to take this into account. | |||
| 1694 | # $len length of best match (greatest wins) | |||
| 1695 | # $tmp string after best match | |||
| 1696 | # $dir direction (prior, after) of best match | |||
| 1697 | # | |||
| 1698 | # $tmp2 string before/after current match | |||
| 1699 | # $tmpl length of current match | |||
| 1700 | ||||
| 1701 | $len=0; | |||
| 1702 | $tmp=$_; | |||
| 1703 | $dir=1; | |||
| 1704 | ||||
| 1705 | $tmp2=$_; | |||
| 1706 | if ($tmp2 =~ s/(^|[^a-z])($future)($|[^a-z])/$1 $3/i) { | |||
| 1707 | $tmpl=length($2); | |||
| 1708 | if ($tmpl>$len) { | |||
| 1709 | $tmp=$tmp2; | |||
| 1710 | $dir=1; | |||
| 1711 | $len=$tmpl; | |||
| 1712 | } | |||
| 1713 | } | |||
| 1714 | ||||
| 1715 | $tmp2=$_; | |||
| 1716 | if ($tmp2 =~ s/(^|[^a-z])($later)($|[^a-z])/$1 $3/i) { | |||
| 1717 | $tmpl=length($2); | |||
| 1718 | if ($tmpl>$len) { | |||
| 1719 | $tmp=$tmp2; | |||
| 1720 | $dir=1; | |||
| 1721 | $len=$tmpl; | |||
| 1722 | } | |||
| 1723 | } | |||
| 1724 | ||||
| 1725 | $tmp2=$_; | |||
| 1726 | if ($tmp2 =~ s/(^|[^a-z])($past)($|[^a-z])/$1 $3/i) { | |||
| 1727 | $tmpl=length($2); | |||
| 1728 | if ($tmpl>$len) { | |||
| 1729 | $tmp=$tmp2; | |||
| 1730 | $dir=-1; | |||
| 1731 | $len=$tmpl; | |||
| 1732 | } | |||
| 1733 | } | |||
| 1734 | ||||
| 1735 | $_ = $tmp; | |||
| 1736 | s/\s*$//; | |||
| 1737 | ||||
| 1738 | # the colon part of the delta | |||
| 1739 | $colon=""; | |||
| 1740 | if (s/($signexp?$numexp?(:($signexp?$numexp)?){1,6})$//) { | |||
| 1741 | $colon=$1; | |||
| 1742 | s/\s+$//; | |||
| 1743 | } | |||
| 1744 | @colon=split(/:/,$colon); | |||
| 1745 | ||||
| 1746 | # the non-colon part of the delta | |||
| 1747 | $sign="+"; | |||
| 1748 | @delta=(); | |||
| 1749 | $i=6; | |||
| 1750 | foreach $exp1 ($yexp,$mexp,$wexp,$dexp,$hexp,$mnexp,$sexp) { | |||
| 1751 | last if ($#colon>=$i--); | |||
| 1752 | $val=0; | |||
| 1753 | if (s/^$exp1//ix) { | |||
| 1754 | $val=$2 if ($2); | |||
| 1755 | $sign=$1 if ($1); | |||
| 1756 | } | |||
| 1757 | ||||
| 1758 | # Collapse a sign like '+ -' into a single character like '-', | |||
| 1759 | # by counting the occurrences of '-'. | |||
| 1760 | # | |||
| 1761 | $sign =~ s/\s+//g; | |||
| 1762 | $sign =~ tr/+//d; | |||
| 1763 | my $count = ($sign =~ tr/-//d); | |||
| 1764 | die "bad characters in sign: $sign" if length $sign; | |||
| 1765 | $sign = $count % 2 ? '-' : '+'; | |||
| 1766 | ||||
| 1767 | push(@delta,"$sign$val"); | |||
| 1768 | } | |||
| 1769 | if (! /^\s*$/) { | |||
| 1770 | pop(@a); | |||
| 1771 | next PARSE; | |||
| 1772 | } | |||
| 1773 | ||||
| 1774 | # make sure that the colon part has a sign | |||
| 1775 | for ($i=0; $i<=$#colon; $i++) { | |||
| 1776 | $val=0; | |||
| 1777 | if ($colon[$i] =~ /^$signexp$numexp?/) { | |||
| 1778 | $val=$2 if ($2); | |||
| 1779 | $sign=$1 if ($1); | |||
| 1780 | } | |||
| 1781 | $colon[$i] = "$sign$val"; | |||
| 1782 | } | |||
| 1783 | ||||
| 1784 | # combine the two | |||
| 1785 | push(@delta,@colon); | |||
| 1786 | if ($dir<0) { | |||
| 1787 | for ($i=0; $i<=$#delta; $i++) { | |||
| 1788 | $delta[$i] =~ tr/-+/+-/; | |||
| 1789 | } | |||
| 1790 | } | |||
| 1791 | ||||
| 1792 | # form the delta and shift off the valid part | |||
| 1793 | $delta=join(":",@delta); | |||
| 1794 | splice(@args,0,$#a+1); | |||
| 1795 | @$args=@args if (defined $ref and $ref eq "ARRAY"); | |||
| 1796 | last PARSE; | |||
| 1797 | } | |||
| 1798 | ||||
| 1799 | $delta=_Delta_Normalize($delta,$Curr{"Mode"}); | |||
| 1800 | return $delta; | |||
| 1801 | } | |||
| 1802 | ||||
| 1803 | sub UnixDate { | |||
| 1804 | print "DEBUG: UnixDate\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 1805 | my($date,@format)=@_; | |||
| 1806 | local($_)=(); | |||
| 1807 | my($format,%f,$out,@out,$c,$date1,$date2,$tmp)=(); | |||
| 1808 | my($scalar)=(); | |||
| 1809 | $date=ParseDateString($date); | |||
| 1810 | return if (! $date); | |||
| 1811 | ||||
| 1812 | my($y,$m,$d,$h,$mn,$s)=($f{"Y"},$f{"m"},$f{"d"},$f{"H"},$f{"M"},$f{"S"})= | |||
| 1813 | _Date_Split($date, 1); | |||
| 1814 | $f{"y"}=substr $f{"Y"},2; | |||
| 1815 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 1816 | ||||
| 1817 | if (! wantarray) { | |||
| 1818 | $format=join(" ",@format); | |||
| 1819 | @format=($format); | |||
| 1820 | $scalar=1; | |||
| 1821 | } | |||
| 1822 | ||||
| 1823 | # month, week | |||
| 1824 | $_=$m; | |||
| 1825 | s/^0//; | |||
| 1826 | $f{"b"}=$f{"h"}=$Lang{$Cnf{"Language"}}{"MonL"}[$_-1]; | |||
| 1827 | $f{"B"}=$Lang{$Cnf{"Language"}}{"MonthL"}[$_-1]; | |||
| 1828 | $_=$m; | |||
| 1829 | s/^0/ /; | |||
| 1830 | $f{"f"}=$_; | |||
| 1831 | $f{"U"}=Date_WeekOfYear($m,$d,$y,7); | |||
| 1832 | $f{"W"}=Date_WeekOfYear($m,$d,$y,1); | |||
| 1833 | ||||
| 1834 | # check week 52,53 and 0 | |||
| 1835 | $f{"G"}=$f{"L"}=$y; | |||
| 1836 | if ($f{"W"}>=52 || $f{"U"}>=52) { | |||
| 1837 | my($dd,$mm,$yy)=($d,$m,$y); | |||
| 1838 | $dd+=7; | |||
| 1839 | if ($dd>31) { | |||
| 1840 | $dd-=31; | |||
| 1841 | $mm=1; | |||
| 1842 | $yy++; | |||
| 1843 | if (Date_WeekOfYear($mm,$dd,$yy,1)==2) { | |||
| 1844 | $f{"G"}=$yy; | |||
| 1845 | $f{"W"}=1; | |||
| 1846 | } | |||
| 1847 | if (Date_WeekOfYear($mm,$dd,$yy,7)==2) { | |||
| 1848 | $f{"L"}=$yy; | |||
| 1849 | $f{"U"}=1; | |||
| 1850 | } | |||
| 1851 | } | |||
| 1852 | } | |||
| 1853 | if ($f{"W"}==0) { | |||
| 1854 | my($dd,$mm,$yy)=($d,$m,$y); | |||
| 1855 | $dd-=7; | |||
| 1856 | $dd+=31 if ($dd<1); | |||
| 1857 | $yy = sprintf "%04d", $yy-1; | |||
| 1858 | $mm=12; | |||
| 1859 | $f{"G"}=$yy; | |||
| 1860 | $f{"W"}=Date_WeekOfYear($mm,$dd,$yy,1)+1; | |||
| 1861 | } | |||
| 1862 | if ($f{"U"}==0) { | |||
| 1863 | my($dd,$mm,$yy)=($d,$m,$y); | |||
| 1864 | $dd-=7; | |||
| 1865 | $dd+=31 if ($dd<1); | |||
| 1866 | $yy = sprintf "%04d", $yy-1; | |||
| 1867 | $mm=12; | |||
| 1868 | $f{"L"}=$yy; | |||
| 1869 | $f{"U"}=Date_WeekOfYear($mm,$dd,$yy,7)+1; | |||
| 1870 | } | |||
| 1871 | ||||
| 1872 | $f{"U"}="0".$f{"U"} if (length $f{"U"} < 2); | |||
| 1873 | $f{"W"}="0".$f{"W"} if (length $f{"W"} < 2); | |||
| 1874 | ||||
| 1875 | # day | |||
| 1876 | $f{"j"}=Date_DayOfYear($m,$d,$y); | |||
| 1877 | $f{"j"} = "0" . $f{"j"} while (length($f{"j"})<3); | |||
| 1878 | $_=$d; | |||
| 1879 | s/^0/ /; | |||
| 1880 | $f{"e"}=$_; | |||
| 1881 | $f{"w"}=Date_DayOfWeek($m,$d,$y); | |||
| 1882 | $f{"v"}=$Lang{$Cnf{"Language"}}{"WL"}[$f{"w"}-1]; | |||
| 1883 | $f{"v"}=" ".$f{"v"} if (length $f{"v"} < 2); | |||
| 1884 | $f{"a"}=$Lang{$Cnf{"Language"}}{"WkL"}[$f{"w"}-1]; | |||
| 1885 | $f{"A"}=$Lang{$Cnf{"Language"}}{"WeekL"}[$f{"w"}-1]; | |||
| 1886 | $f{"E"}=Date_DaySuffix($f{"e"}); | |||
| 1887 | ||||
| 1888 | # hour | |||
| 1889 | $_=$h; | |||
| 1890 | s/^0/ /; | |||
| 1891 | $f{"k"}=$_; | |||
| 1892 | $f{"i"}=$f{"k"}+1; | |||
| 1893 | $f{"i"}=$f{"k"}; | |||
| 1894 | $f{"i"}=12 if ($f{"k"}==0); | |||
| 1895 | $f{"i"}=$f{"k"}-12 if ($f{"k"}>12); | |||
| 1896 | $f{"i"}=$f{"i"}-12 if ($f{"i"}>12); | |||
| 1897 | $f{"i"}=" ".$f{"i"} if (length($f{"i"})<2); | |||
| 1898 | $f{"I"}=$f{"i"}; | |||
| 1899 | $f{"I"}=~ s/^ /0/; | |||
| 1900 | $f{"p"}=$Lang{$Cnf{"Language"}}{"AMstr"}; | |||
| 1901 | $f{"p"}=$Lang{$Cnf{"Language"}}{"PMstr"} if ($f{"k"}>11); | |||
| 1902 | ||||
| 1903 | # minute, second, timezone | |||
| 1904 | $f{"o"}=Date_SecsSince1970($m,$d,$y,$h,$mn,$s); | |||
| 1905 | $f{"s"}=Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s); | |||
| 1906 | $f{"Z"}=($Cnf{"ConvTZ"} eq "IGNORE" or $Cnf{"ConvTZ"} eq "") ? | |||
| 1907 | $Cnf{"TZ"} : $Cnf{"ConvTZ"}; | |||
| 1908 | $f{"z"}=($f{"Z"}=~/^[+-]\d{4}/) ? $f{"Z"} : ($Zone{"n2o"}{lc $f{"Z"}} || ""); | |||
| 1909 | ||||
| 1910 | # date, time | |||
| 1911 | $f{"c"}=qq|$f{"a"} $f{"b"} $f{"e"} $h:$mn:$s $y|; | |||
| 1912 | $f{"C"}=$f{"u"}= | |||
| 1913 | qq|$f{"a"} $f{"b"} $f{"e"} $h:$mn:$s $f{"z"} $y|; | |||
| 1914 | $f{"g"}=qq|$f{"a"}, $d $f{"b"} $y $h:$mn:$s $f{"z"}|; | |||
| 1915 | $f{"D"}=$f{"x"}=qq|$m/$d/$f{"y"}|; | |||
| 1916 | $f{"x"}=qq|$d/$m/$f{"y"}| if ($Cnf{"DateFormat"} ne "US"); | |||
| 1917 | $f{"r"}=qq|$f{"I"}:$mn:$s $f{"p"}|; | |||
| 1918 | $f{"R"}=qq|$h:$mn|; | |||
| 1919 | $f{"T"}=$f{"X"}=qq|$h:$mn:$s|; | |||
| 1920 | $f{"V"}=qq|$m$d$h$mn$f{"y"}|; | |||
| 1921 | $f{"Q"}="$y$m$d"; | |||
| 1922 | $f{"q"}=qq|$y$m$d$h$mn$s|; | |||
| 1923 | $f{"P"}=qq|$y$m$d$h:$mn:$s|; | |||
| 1924 | $f{"O"}=qq|$y-$m-${d}T$h:$mn:$s|; | |||
| 1925 | $f{"F"}=qq|$f{"A"}, $f{"B"} $f{"e"}, $f{"Y"}|; | |||
| 1926 | if ($f{"W"}==0) { | |||
| 1927 | $y--; | |||
| 1928 | $tmp=Date_WeekOfYear(12,31,$y,1); | |||
| 1929 | $tmp="0$tmp" if (length($tmp) < 2); | |||
| 1930 | $f{"J"}=qq|$y-W$tmp-$f{"w"}|; | |||
| 1931 | } else { | |||
| 1932 | $f{"J"}=qq|$f{"G"}-W$f{"W"}-$f{"w"}|; | |||
| 1933 | } | |||
| 1934 | $f{"K"}=qq|$y-$f{"j"}|; | |||
| 1935 | # %l is a special case. Since it requires the use of the calculator | |||
| 1936 | # which requires this routine, an infinite recursion results. To get | |||
| 1937 | # around this, %l is NOT determined every time this is called so the | |||
| 1938 | # recursion breaks. | |||
| 1939 | ||||
| 1940 | # other formats | |||
| 1941 | $f{"n"}="\n"; | |||
| 1942 | $f{"t"}="\t"; | |||
| 1943 | $f{"%"}="%"; | |||
| 1944 | $f{"+"}="+"; | |||
| 1945 | ||||
| 1946 | foreach $format (@format) { | |||
| 1947 | $format=reverse($format); | |||
| 1948 | $out=""; | |||
| 1949 | while ($format ne "") { | |||
| 1950 | $c=chop($format); | |||
| 1951 | if ($c eq "%") { | |||
| 1952 | $c=chop($format); | |||
| 1953 | if ($c eq "l") { | |||
| 1954 | Date_Init(); | |||
| 1955 | $date1=_DateCalc_DateDelta($Curr{"Now"},"-0:6:0:0:0:0:0"); | |||
| 1956 | $date2=_DateCalc_DateDelta($Curr{"Now"},"+0:6:0:0:0:0:0"); | |||
| 1957 | if (Date_Cmp($date,$date1)>=0 && Date_Cmp($date,$date2)<=0) { | |||
| 1958 | $f{"l"}=qq|$f{"b"} $f{"e"} $h:$mn|; | |||
| 1959 | } else { | |||
| 1960 | $f{"l"}=qq|$f{"b"} $f{"e"} $f{"Y"}|; | |||
| 1961 | } | |||
| 1962 | $out .= $f{"$c"}; | |||
| 1963 | } elsif (exists $f{"$c"}) { | |||
| 1964 | $out .= $f{"$c"}; | |||
| 1965 | } else { | |||
| 1966 | $out .= $c; | |||
| 1967 | } | |||
| 1968 | } else { | |||
| 1969 | $out .= $c; | |||
| 1970 | } | |||
| 1971 | } | |||
| 1972 | push(@out,$out); | |||
| 1973 | } | |||
| 1974 | if ($scalar) { | |||
| 1975 | return $out[0]; | |||
| 1976 | } else { | |||
| 1977 | return (@out); | |||
| 1978 | } | |||
| 1979 | } | |||
| 1980 | ||||
| 1981 | # Can't be in "use integer" because we're doing decimal arithmatic | |||
| 1982 | 3 | 887µs | 296µs | no integer; # spent 23µs making 1 call to integer::unimport |
| 1983 | sub Delta_Format { | |||
| 1984 | print "DEBUG: Delta_Format\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 1985 | my($delta,@arg)=@_; | |||
| 1986 | my($mode); | |||
| 1987 | if (lc($arg[0]) eq "approx") { | |||
| 1988 | $mode = "approx"; | |||
| 1989 | shift(@arg); | |||
| 1990 | } else { | |||
| 1991 | $mode = "exact"; | |||
| 1992 | } | |||
| 1993 | my($dec,@format) = @arg; | |||
| 1994 | ||||
| 1995 | $delta=ParseDateDelta($delta); | |||
| 1996 | return "" if (! $delta); | |||
| 1997 | my(@out,%f,$out,$c1,$c2,$scalar,$format)=(); | |||
| 1998 | local($_)=$delta; | |||
| 1999 | my($y,$M,$w,$d,$h,$m,$s)=_Delta_Split($delta); | |||
| 2000 | # Get rid of positive signs. | |||
| 2001 | ($y,$M,$w,$d,$h,$m,$s)=map { 1*$_; }($y,$M,$w,$d,$h,$m,$s); | |||
| 2002 | ||||
| 2003 | if (defined $dec && $dec>0) { | |||
| 2004 | $dec="%." . ($dec*1) . "f"; | |||
| 2005 | } else { | |||
| 2006 | $dec="%f"; | |||
| 2007 | } | |||
| 2008 | ||||
| 2009 | if (! wantarray) { | |||
| 2010 | $format=join(" ",@format); | |||
| 2011 | @format=($format); | |||
| 2012 | $scalar=1; | |||
| 2013 | } | |||
| 2014 | ||||
| 2015 | # Length of each unit in seconds | |||
| 2016 | my($sl,$ml,$hl,$dl,$wl,$Ml,$yl)=(); | |||
| 2017 | $sl = 1; | |||
| 2018 | $ml = $sl*60; | |||
| 2019 | $hl = $ml*60; | |||
| 2020 | $dl = $hl*24; | |||
| 2021 | $wl = $dl*7; | |||
| 2022 | $yl = $dl*365.25; | |||
| 2023 | $Ml = $yl/12; | |||
| 2024 | ||||
| 2025 | # The decimal amount of each unit contained in all smaller units | |||
| 2026 | my($yd,$Md,$sd,$md,$hd,$dd,$wd)=(); | |||
| 2027 | if ($mode eq "exact") { | |||
| 2028 | $yd = $M/12; | |||
| 2029 | $Md = 0; | |||
| 2030 | } else { | |||
| 2031 | $yd = ($M*$Ml + $w*$wl + $d*$dl + $h*$hl + $m*$ml + $s*$sl)/$yl; | |||
| 2032 | $Md = ($w*$wl + $d*$dl + $h*$hl + $m*$ml + $s*$sl)/$Ml; | |||
| 2033 | } | |||
| 2034 | ||||
| 2035 | $wd = ($d*$dl + $h*$hl + $m*$ml + $s*$sl)/$wl; | |||
| 2036 | $dd = ($h*$hl + $m*$ml + $s*$sl)/$dl; | |||
| 2037 | $hd = ($m*$ml + $s*$sl)/$hl; | |||
| 2038 | $md = ($s*$sl)/$ml; | |||
| 2039 | $sd = 0; | |||
| 2040 | ||||
| 2041 | # The amount of each unit contained in higher units. | |||
| 2042 | my($yh,$Mh,$sh,$mh,$hh,$dh,$wh)=(); | |||
| 2043 | $yh = 0; | |||
| 2044 | $Mh = ($yh+$y)*12; | |||
| 2045 | ||||
| 2046 | if ($mode eq "exact") { | |||
| 2047 | $wh = 0; | |||
| 2048 | $dh = ($wh+$w)*7; | |||
| 2049 | } else { | |||
| 2050 | $wh = ($yh+$y+$M/12)*365.25/7; | |||
| 2051 | $dh = ($wh+$w)*7; | |||
| 2052 | } | |||
| 2053 | ||||
| 2054 | $hh = ($dh+$d)*24; | |||
| 2055 | $mh = ($hh+$h)*60; | |||
| 2056 | $sh = ($mh+$m)*60; | |||
| 2057 | ||||
| 2058 | # Set up the formats | |||
| 2059 | ||||
| 2060 | $f{"yv"} = $y; | |||
| 2061 | $f{"Mv"} = $M; | |||
| 2062 | $f{"wv"} = $w; | |||
| 2063 | $f{"dv"} = $d; | |||
| 2064 | $f{"hv"} = $h; | |||
| 2065 | $f{"mv"} = $m; | |||
| 2066 | $f{"sv"} = $s; | |||
| 2067 | ||||
| 2068 | $f{"yh"} = $y+$yh; | |||
| 2069 | $f{"Mh"} = $M+$Mh; | |||
| 2070 | $f{"wh"} = $w+$wh; | |||
| 2071 | $f{"dh"} = $d+$dh; | |||
| 2072 | $f{"hh"} = $h+$hh; | |||
| 2073 | $f{"mh"} = $m+$mh; | |||
| 2074 | $f{"sh"} = $s+$sh; | |||
| 2075 | ||||
| 2076 | $f{"yd"} = sprintf($dec,$y+$yd); | |||
| 2077 | $f{"Md"} = sprintf($dec,$M+$Md); | |||
| 2078 | $f{"wd"} = sprintf($dec,$w+$wd); | |||
| 2079 | $f{"dd"} = sprintf($dec,$d+$dd); | |||
| 2080 | $f{"hd"} = sprintf($dec,$h+$hd); | |||
| 2081 | $f{"md"} = sprintf($dec,$m+$md); | |||
| 2082 | $f{"sd"} = sprintf($dec,$s+$sd); | |||
| 2083 | ||||
| 2084 | $f{"yt"} = sprintf($dec,$yh+$y+$yd); | |||
| 2085 | $f{"Mt"} = sprintf($dec,$Mh+$M+$Md); | |||
| 2086 | $f{"wt"} = sprintf($dec,$wh+$w+$wd); | |||
| 2087 | $f{"dt"} = sprintf($dec,$dh+$d+$dd); | |||
| 2088 | $f{"ht"} = sprintf($dec,$hh+$h+$hd); | |||
| 2089 | $f{"mt"} = sprintf($dec,$mh+$m+$md); | |||
| 2090 | $f{"st"} = sprintf($dec,$sh+$s+$sd); | |||
| 2091 | ||||
| 2092 | $f{"%"} = "%"; | |||
| 2093 | ||||
| 2094 | foreach $format (@format) { | |||
| 2095 | $format=reverse($format); | |||
| 2096 | $out=""; | |||
| 2097 | PARSE: while ($format) { | |||
| 2098 | $c1=chop($format); | |||
| 2099 | if ($c1 eq "%") { | |||
| 2100 | $c1=chop($format); | |||
| 2101 | if (exists($f{$c1})) { | |||
| 2102 | $out .= $f{$c1}; | |||
| 2103 | next PARSE; | |||
| 2104 | } | |||
| 2105 | $c2=chop($format); | |||
| 2106 | if (exists($f{"$c1$c2"})) { | |||
| 2107 | $out .= $f{"$c1$c2"}; | |||
| 2108 | next PARSE; | |||
| 2109 | } | |||
| 2110 | $out .= $c1; | |||
| 2111 | $format .= $c2; | |||
| 2112 | } else { | |||
| 2113 | $out .= $c1; | |||
| 2114 | } | |||
| 2115 | } | |||
| 2116 | push(@out,$out); | |||
| 2117 | } | |||
| 2118 | if ($scalar) { | |||
| 2119 | return $out[0]; | |||
| 2120 | } else { | |||
| 2121 | return (@out); | |||
| 2122 | } | |||
| 2123 | } | |||
| 2124 | 3 | 8.32ms | 2.77ms | use integer; # spent 10µs making 1 call to integer::import |
| 2125 | ||||
| 2126 | sub ParseRecur { | |||
| 2127 | print "DEBUG: ParseRecur\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 2128 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 2129 | ||||
| 2130 | my($recur,$dateb,$date0,$date1,$flag)=@_; | |||
| 2131 | local($_)=$recur; | |||
| 2132 | ||||
| 2133 | my($recur_0,$recur_1,@recur0,@recur1)=(); | |||
| 2134 | my(@tmp,$tmp,$each,$num,$y,$m,$d,$w,$h,$mn,$s,$delta,$y0,$y1,$yb)=(); | |||
| 2135 | my($yy,$n,$dd,@d,@tmp2,$date,@date,@w,@tmp3,@m,@y,$tmp2,$d2,@flags)=(); | |||
| 2136 | ||||
| 2137 | # $date0, $date1, $dateb, $flag : passed in (these are always the final say | |||
| 2138 | # in determining whether a date matches a | |||
| 2139 | # recurrence IF they are present. | |||
| 2140 | # $date_b, $date_0, $date_1 : if a value can be determined from the | |||
| 2141 | # $flag_t recurrence, they are stored here. | |||
| 2142 | # | |||
| 2143 | # If values can be determined from the recurrence AND are passed in, the | |||
| 2144 | # following are used: | |||
| 2145 | # max($date0,$date_0) i.e. the later of the two dates | |||
| 2146 | # min($date1,$date_1) i.e. the earlier of the two dates | |||
| 2147 | # | |||
| 2148 | # The base date that is used is the first one defined from | |||
| 2149 | # $dateb $date_b | |||
| 2150 | # The base date is only used if necessary (as determined by the recur). | |||
| 2151 | # For example, "every other friday" requires a base date, but "2nd | |||
| 2152 | # friday of every month" doesn't. | |||
| 2153 | ||||
| 2154 | my($date_b,$date_0,$date_1,$flag_t); | |||
| 2155 | ||||
| 2156 | # | |||
| 2157 | # Check the arguments passed in. | |||
| 2158 | # | |||
| 2159 | ||||
| 2160 | $date0="" if (! defined $date0); | |||
| 2161 | $date1="" if (! defined $date1); | |||
| 2162 | $dateb="" if (! defined $dateb); | |||
| 2163 | $flag ="" if (! defined $flag); | |||
| 2164 | ||||
| 2165 | if ($dateb) { | |||
| 2166 | $dateb=ParseDateString($dateb); | |||
| 2167 | return "" if (! $dateb); | |||
| 2168 | } | |||
| 2169 | if ($date0) { | |||
| 2170 | $date0=ParseDateString($date0); | |||
| 2171 | return "" if (! $date0); | |||
| 2172 | } | |||
| 2173 | if ($date1) { | |||
| 2174 | $date1=ParseDateString($date1); | |||
| 2175 | return "" if (! $date1); | |||
| 2176 | } | |||
| 2177 | ||||
| 2178 | # | |||
| 2179 | # Parse the recur. $date_b, $date_0, and $date_e are values obtained | |||
| 2180 | # from the recur. | |||
| 2181 | # | |||
| 2182 | ||||
| 2183 | @tmp=_Recur_Split($_); | |||
| 2184 | ||||
| 2185 | if (@tmp) { | |||
| 2186 | ($recur_0,$recur_1,$flag_t,$date_b,$date_0,$date_1)=@tmp; | |||
| 2187 | $recur_0 = "" if (! defined $recur_0); | |||
| 2188 | $recur_1 = "" if (! defined $recur_1); | |||
| 2189 | $flag_t = "" if (! defined $flag_t); | |||
| 2190 | $date_b = "" if (! defined $date_b); | |||
| 2191 | $date_0 = "" if (! defined $date_0); | |||
| 2192 | $date_1 = "" if (! defined $date_1); | |||
| 2193 | ||||
| 2194 | @recur0 = split(/:/,$recur_0); | |||
| 2195 | @recur1 = split(/:/,$recur_1); | |||
| 2196 | return "" if ($#recur0 + $#recur1 + 2 != 7); | |||
| 2197 | ||||
| 2198 | if ($date_b) { | |||
| 2199 | $date_b=ParseDateString($date_b); | |||
| 2200 | return "" if (! $date_b); | |||
| 2201 | } | |||
| 2202 | if ($date_0) { | |||
| 2203 | $date_0=ParseDateString($date_0); | |||
| 2204 | return "" if (! $date_0); | |||
| 2205 | } | |||
| 2206 | if ($date_1) { | |||
| 2207 | $date_1=ParseDateString($date_1); | |||
| 2208 | return "" if (! $date_1); | |||
| 2209 | } | |||
| 2210 | ||||
| 2211 | } else { | |||
| 2212 | ||||
| 2213 | my($mmm)='\s*'.$Lang{$Cnf{"Language"}}{"Month"}; # \s*(jan|january|...) | |||
| 2214 | my(%mmm)=%{ $Lang{$Cnf{"Language"}}{"MonthH"} }; # { jan=>1, ... } | |||
| 2215 | my($wkexp)='\s*'.$Lang{$Cnf{"Language"}}{"Week"}; # \s*(mon|monday|...) | |||
| 2216 | my(%week)=%{ $Lang{$Cnf{"Language"}}{"WeekH"} }; # { monday=>1, ... } | |||
| 2217 | my($day)='\s*'.$Lang{$Cnf{"Language"}}{"Dabb"}; # \s*(?:d|day|days) | |||
| 2218 | my($month)='\s*'.$Lang{$Cnf{"Language"}}{"Mabb"}; # \s*(?:mon|month|months) | |||
| 2219 | my($week)='\s*'.$Lang{$Cnf{"Language"}}{"Wabb"}; # \s*(?:w|wk|week|weeks) | |||
| 2220 | my($daysexp)=$Lang{$Cnf{"Language"}}{"DoM"}; # (1st|first|...31st) | |||
| 2221 | my(%dayshash)=%{ $Lang{$Cnf{"Language"}}{"DoMH"} }; | |||
| 2222 | # { 1st=>1,first=>1,...} | |||
| 2223 | my($of)='\s*'.$Lang{$Cnf{"Language"}}{"Of"}; # \s*(?:in|of) | |||
| 2224 | my($lastexp)=$Lang{$Cnf{"Language"}}{"Last"}; # (?:last) | |||
| 2225 | my($each)=$Lang{$Cnf{"Language"}}{"Each"}; # (?:each|every) | |||
| 2226 | ||||
| 2227 | my($D)='\s*(\d+)'; | |||
| 2228 | my($Y)='\s*(\d{4}|\d{2})'; | |||
| 2229 | ||||
| 2230 | # Change 1st to 1 | |||
| 2231 | if (/(^|[^a-z])$daysexp($|[^a-z])/i) { | |||
| 2232 | $tmp=lc($2); | |||
| 2233 | $tmp=$dayshash{"$tmp"}; | |||
| 2234 | s/(^|[^a-z])$daysexp($|[^a-z])/$1 $tmp $3/i; | |||
| 2235 | } | |||
| 2236 | s/\s*$//; | |||
| 2237 | ||||
| 2238 | # Get rid of "each" | |||
| 2239 | if (/(^|[^a-z])$each($|[^a-z])/i) { | |||
| 2240 | s/(^|[^a-z])$each($|[^a-z])/$1 $2/i; | |||
| 2241 | $each=1; | |||
| 2242 | } else { | |||
| 2243 | $each=0; | |||
| 2244 | } | |||
| 2245 | ||||
| 2246 | if ($each) { | |||
| 2247 | ||||
| 2248 | if (/^$D?$day(?:$of$mmm?$Y)?$/i || | |||
| 2249 | /^$D?$day(?:$of$mmm())?$/i) { | |||
| 2250 | # every [2nd] day in [june] 1997 | |||
| 2251 | # every [2nd] day [in june] | |||
| 2252 | ($num,$m,$y)=($1,$2,$3); | |||
| 2253 | $num=1 if (! defined $num); | |||
| 2254 | $m="" if (! defined $m); | |||
| 2255 | $y="" if (! defined $y); | |||
| 2256 | ||||
| 2257 | $y=$Curr{"Y"} if (! $y); | |||
| 2258 | if ($m) { | |||
| 2259 | $m=$mmm{lc($m)}; | |||
| 2260 | $date_0=_Date_Join($y,$m,1,0,0,0); | |||
| 2261 | $date_1=_DateCalc_DateDelta($date_0,"+0:1:0:0:0:0:0",0); | |||
| 2262 | } else { | |||
| 2263 | $date_0=_Date_Join($y, 1,1,0,0,0); | |||
| 2264 | $date_1=_Date_Join($y+1,1,1,0,0,0); | |||
| 2265 | } | |||
| 2266 | $date_b=DateCalc($date_0,"-0:0:0:1:0:0:0",0); | |||
| 2267 | @recur0=(0,0,0,$num,0,0,0); | |||
| 2268 | @recur1=(); | |||
| 2269 | ||||
| 2270 | } elsif (/^$D$day?$of$month(?:$of?$Y)?$/) { | |||
| 2271 | # 2nd [day] of every month [in 1997] | |||
| 2272 | ($num,$y)=($1,$2); | |||
| 2273 | $y=$Curr{"Y"} if (! $y); | |||
| 2274 | ||||
| 2275 | $date_0=_Date_Join($y, 1,1,0,0,0); | |||
| 2276 | $date_1=_Date_Join($y+1,1,1,0,0,0); | |||
| 2277 | $date_b=$date_0; | |||
| 2278 | ||||
| 2279 | @recur0=(0,1,0); | |||
| 2280 | @recur1=($num,0,0,0); | |||
| 2281 | ||||
| 2282 | } elsif (/^$D$wkexp$of$month(?:$of?$Y)?$/ || | |||
| 2283 | /^($lastexp)$wkexp$of$month(?:$of?$Y)?$/) { | |||
| 2284 | # 2nd tuesday of every month [in 1997] | |||
| 2285 | # last tuesday of every month [in 1997] | |||
| 2286 | ($num,$d,$y)=($1,$2,$3); | |||
| 2287 | $y=$Curr{"Y"} if (! $y); | |||
| 2288 | $d=$week{lc($d)}; | |||
| 2289 | $num=-1 if ($num !~ /^$D$/); | |||
| 2290 | ||||
| 2291 | $date_0=_Date_Join($y,1,1,0,0,0); | |||
| 2292 | $date_1=_Date_Join($y+1,1,1,0,0,0); | |||
| 2293 | $date_b=$date_0; | |||
| 2294 | ||||
| 2295 | @recur0=(0,1); | |||
| 2296 | @recur1=($num,$d,0,0,0); | |||
| 2297 | ||||
| 2298 | } elsif (/^$D?$wkexp(?:$of$mmm?$Y)?$/i || | |||
| 2299 | /^$D?$wkexp(?:$of$mmm())?$/i) { | |||
| 2300 | # every tuesday in june 1997 | |||
| 2301 | # every 2nd tuesday in june 1997 | |||
| 2302 | ($num,$d,$m,$y)=($1,$2,$3,$4); | |||
| 2303 | $y=$Curr{"Y"} if (! $y); | |||
| 2304 | $num=1 if (! defined $num); | |||
| 2305 | $m="" if (! defined $m); | |||
| 2306 | $d=$week{lc($d)}; | |||
| 2307 | ||||
| 2308 | if ($m) { | |||
| 2309 | $m=$mmm{lc($m)}; | |||
| 2310 | $date_0=_Date_Join($y,$m,1,0,0,0); | |||
| 2311 | $date_1=_DateCalc_DateDelta($date_0,"+0:1:0:0:0:0:0",0); | |||
| 2312 | } else { | |||
| 2313 | $date_0=_Date_Join($y,1,1,0,0,0); | |||
| 2314 | $date_1=_Date_Join($y+1,1,1,0,0,0); | |||
| 2315 | } | |||
| 2316 | $date_b=DateCalc($date_0,"-0:0:0:1:0:0:0",0); | |||
| 2317 | ||||
| 2318 | @recur0=(0,0,$num); | |||
| 2319 | @recur1=($d,0,0,0); | |||
| 2320 | ||||
| 2321 | } else { | |||
| 2322 | return ""; | |||
| 2323 | } | |||
| 2324 | ||||
| 2325 | $date_0="" if ($date0); | |||
| 2326 | $date_1="" if ($date1); | |||
| 2327 | } else { | |||
| 2328 | return ""; | |||
| 2329 | } | |||
| 2330 | } | |||
| 2331 | ||||
| 2332 | # | |||
| 2333 | # Override with any values passed in | |||
| 2334 | # | |||
| 2335 | ||||
| 2336 | $date0 = $date_0 if (! $date0); | |||
| 2337 | $date1 = $date_1 if (! $date1); | |||
| 2338 | $dateb = $date_b if (! $dateb); | |||
| 2339 | if ($flag =~ s/^\+//) { | |||
| 2340 | $flag = "$flag_t,$flag" if ($flag_t); | |||
| 2341 | } | |||
| 2342 | $flag = $flag_t if (! $flag); | |||
| 2343 | $flag = "" if (! $flag); | |||
| 2344 | ||||
| 2345 | if (! wantarray) { | |||
| 2346 | $tmp = join(":",@recur0); | |||
| 2347 | $tmp .= "*" . join(":",@recur1) if (@recur1); | |||
| 2348 | $tmp .= "*$flag*$dateb*$date0*$date1"; | |||
| 2349 | return $tmp; | |||
| 2350 | } | |||
| 2351 | if (@recur0) { | |||
| 2352 | return () if (! $date0 || ! $date1); # dateb is NOT required in all case | |||
| 2353 | } | |||
| 2354 | ||||
| 2355 | # | |||
| 2356 | # Some flags affect parsing. | |||
| 2357 | # | |||
| 2358 | ||||
| 2359 | @flags = split(/,/,$flag); | |||
| 2360 | my($f); | |||
| 2361 | foreach $f (@flags) { | |||
| 2362 | if ($f =~ /^EASTER$/i) { | |||
| 2363 | ($y,$m,$w,$d,$h,$mn,$s)=(@recur0,@recur1); | |||
| 2364 | # We want something that will return Jan 1 for the given years. | |||
| 2365 | if ($#recur0==-1) { | |||
| 2366 | @recur1=($y,1,0,1,$h,$mn,$s); | |||
| 2367 | } elsif ($#recur0<=3) { | |||
| 2368 | @recur0=($y,0,0,0); | |||
| 2369 | @recur1=($h,$mn,$s); | |||
| 2370 | } elsif ($#recur0==4) { | |||
| 2371 | @recur0=($y,0,0,0,0); | |||
| 2372 | @recur1=($mn,$s); | |||
| 2373 | } elsif ($#recur0==5) { | |||
| 2374 | @recur0=($y,0,0,0,0,0); | |||
| 2375 | @recur1=($s); | |||
| 2376 | } else { | |||
| 2377 | @recur0=($y,0,0,0,0,0,0); | |||
| 2378 | } | |||
| 2379 | } | |||
| 2380 | } | |||
| 2381 | ||||
| 2382 | # | |||
| 2383 | # Determine the dates referenced by the recur. Also, fix the base date | |||
| 2384 | # as necessary for the recurrences which require it. | |||
| 2385 | # | |||
| 2386 | ||||
| 2387 | ($y,$m,$w,$d,$h,$mn,$s)=(@recur0,@recur1); | |||
| 2388 | @y=@m=@w=@d=(); | |||
| 2389 | my(@time)=($h,$mn,$s); | |||
| 2390 | ||||
| 2391 | RECUR: while (1) { | |||
| 2392 | ||||
| 2393 | if ($#recur0==-1) { | |||
| 2394 | # * 0-M-W-D-H-MN-S => 0 * M-W-D-H-MN-S | |||
| 2395 | ||||
| 2396 | if ($y eq "0") { | |||
| 2397 | push(@recur0,1); | |||
| 2398 | shift(@recur1); | |||
| 2399 | next RECUR; | |||
| 2400 | } | |||
| 2401 | ||||
| 2402 | # Y-M-W-D-H-MN-S | |||
| 2403 | ||||
| 2404 | @y=_ReturnList($y); | |||
| 2405 | foreach $y (@y) { | |||
| 2406 | $y=_Date_FixYear($y) if (length($y)==2); | |||
| 2407 | return () if (length($y)!=4 || ! _IsInt($y)); | |||
| 2408 | } | |||
| 2409 | ||||
| 2410 | $date0=ParseDate("0000-01-01") if (! $date0); | |||
| 2411 | $date1=ParseDate("9999-12-31 23:59:59") if (! $date1); | |||
| 2412 | ||||
| 2413 | if ($m eq "0" and $w eq "0") { | |||
| 2414 | ||||
| 2415 | # * Y-0-0-0-H-MN-S | |||
| 2416 | # * Y-0-0-DOY-H-MN-S | |||
| 2417 | ||||
| 2418 | if ($d eq "0") { | |||
| 2419 | @d=(1); | |||
| 2420 | } else { | |||
| 2421 | @d=_ReturnList($d); | |||
| 2422 | return () if (! @d); | |||
| 2423 | foreach $d (@d) { | |||
| 2424 | return () if (! _IsInt($d,-366,366) || $d==0); | |||
| 2425 | } | |||
| 2426 | } | |||
| 2427 | ||||
| 2428 | @date=(); | |||
| 2429 | foreach $yy (@y) { | |||
| 2430 | my $diy = Date_DaysInYear($yy); | |||
| 2431 | foreach $d (@d) { | |||
| 2432 | my $tmpd = $d; | |||
| 2433 | $tmpd += ($diy+1) if ($tmpd < 0); | |||
| 2434 | next if (! _IsInt($tmpd,1,$diy)); | |||
| 2435 | ($y,$m,$dd)=Date_NthDayOfYear($yy,$tmpd); | |||
| 2436 | push(@date, _Date_Join($y,$m,$dd,0,0,0)); | |||
| 2437 | } | |||
| 2438 | } | |||
| 2439 | last RECUR; | |||
| 2440 | ||||
| 2441 | } elsif ($w eq "0") { | |||
| 2442 | ||||
| 2443 | # * Y-M-0-0-H-MN-S | |||
| 2444 | # * Y-M-0-DOM-H-MN-S | |||
| 2445 | ||||
| 2446 | @m=_ReturnList($m); | |||
| 2447 | return () if (! @m); | |||
| 2448 | foreach $m (@m) { | |||
| 2449 | return () if (! _IsInt($m,1,12)); | |||
| 2450 | } | |||
| 2451 | ||||
| 2452 | if ($d eq "0") { | |||
| 2453 | @d=(1); | |||
| 2454 | } else { | |||
| 2455 | @d=_ReturnList($d); | |||
| 2456 | return () if (! @d); | |||
| 2457 | foreach $d (@d) { | |||
| 2458 | return () if (! _IsInt($d,-31,31) || $d==0); | |||
| 2459 | } | |||
| 2460 | } | |||
| 2461 | ||||
| 2462 | @date=(); | |||
| 2463 | foreach $y (@y) { | |||
| 2464 | foreach $m (@m) { | |||
| 2465 | my $dim = Date_DaysInMonth($m,$y); | |||
| 2466 | foreach $d (@d) { | |||
| 2467 | my $tmpd = $d; | |||
| 2468 | $tmpd += ($dim+1) if ($d<0); | |||
| 2469 | next if (! _IsInt($tmpd,1,$dim)); | |||
| 2470 | $date=_Date_Join($y,$m,$tmpd,0,0,0); | |||
| 2471 | push(@date,$date); | |||
| 2472 | } | |||
| 2473 | } | |||
| 2474 | } | |||
| 2475 | last RECUR; | |||
| 2476 | ||||
| 2477 | } elsif ($m eq "0") { | |||
| 2478 | ||||
| 2479 | # * Y-0-WOY-DOW-H-MN-S | |||
| 2480 | # * Y-0-WOY-0-H-MN-S | |||
| 2481 | ||||
| 2482 | @w=_ReturnList($w); | |||
| 2483 | return () if (! @w); | |||
| 2484 | foreach $w (@w) { | |||
| 2485 | return () if (! _IsInt($w,-53,53) || $w==0); | |||
| 2486 | } | |||
| 2487 | ||||
| 2488 | if ($d eq "0") { | |||
| 2489 | @d=(1); | |||
| 2490 | } else { | |||
| 2491 | @d=_ReturnList($d); | |||
| 2492 | return () if (! @d); | |||
| 2493 | foreach $d (@d) { | |||
| 2494 | $d += 8 if ($d<0); | |||
| 2495 | return () if (! _IsInt($d,1,7)); | |||
| 2496 | } | |||
| 2497 | } | |||
| 2498 | ||||
| 2499 | @date=(); | |||
| 2500 | foreach $y (@y) { | |||
| 2501 | foreach $w (@w) { | |||
| 2502 | foreach $d (@d) { | |||
| 2503 | my($tmpw,$del); | |||
| 2504 | if ($w<0) { | |||
| 2505 | $date="$y-12-31-00:00:00"; | |||
| 2506 | $tmpw = (-$w)-1; | |||
| 2507 | $del="-0:0:$tmpw:0:0:0:0"; | |||
| 2508 | $date=Date_GetPrev($date,$d,1); | |||
| 2509 | } else { | |||
| 2510 | $date="$y-01-01-00:00:00"; | |||
| 2511 | $tmpw = ($w)-1; | |||
| 2512 | $del="0:0:$tmpw:0:0:0:0"; | |||
| 2513 | $date=Date_GetNext($date,$d,1); | |||
| 2514 | } | |||
| 2515 | $date=_DateCalc_DateDelta($date,$del); | |||
| 2516 | push(@date,$date) if ( (_Date_Split($date))[0] == $y); | |||
| 2517 | } | |||
| 2518 | } | |||
| 2519 | } | |||
| 2520 | last RECUR; | |||
| 2521 | ||||
| 2522 | } else { | |||
| 2523 | ||||
| 2524 | # * Y-M-WOM-DOW-H-MN-S | |||
| 2525 | # * Y-M-WOM-0-H-MN-S | |||
| 2526 | ||||
| 2527 | @m=_ReturnList($m); | |||
| 2528 | return () if (! @m); | |||
| 2529 | @w=_ReturnList($w); | |||
| 2530 | return () if (! @w); | |||
| 2531 | if ($d eq "0") { | |||
| 2532 | @d=(1); | |||
| 2533 | } else { | |||
| 2534 | @d=_ReturnList($d); | |||
| 2535 | } | |||
| 2536 | ||||
| 2537 | @date=_Date_Recur_WoM(\@y,\@m,\@w,\@d); | |||
| 2538 | last RECUR; | |||
| 2539 | } | |||
| 2540 | } | |||
| 2541 | ||||
| 2542 | if ($#recur0==0) { | |||
| 2543 | ||||
| 2544 | # Y * M-W-D-H-MN-S | |||
| 2545 | $n=$y; | |||
| 2546 | $n=1 if ($n==0); | |||
| 2547 | ||||
| 2548 | if ($m eq "0") { | |||
| 2549 | ||||
| 2550 | # Y * 0-W-D-H-MN-S => Y-0 * W-D-H-MN-S | |||
| 2551 | push(@recur0,0); | |||
| 2552 | shift(@recur1); | |||
| 2553 | ||||
| 2554 | } elsif ($w eq "0") { | |||
| 2555 | ||||
| 2556 | # Y * M-0-DOM-H-MN-S | |||
| 2557 | return () if (! $dateb && $y != 1); | |||
| 2558 | ||||
| 2559 | @m=_ReturnList($m); | |||
| 2560 | return () if (! @m); | |||
| 2561 | foreach $m (@m) { | |||
| 2562 | return () if (! _IsInt($m,1,12)); | |||
| 2563 | } | |||
| 2564 | ||||
| 2565 | if ($d eq "0") { | |||
| 2566 | @d = (1); | |||
| 2567 | } else { | |||
| 2568 | @d=_ReturnList($d); | |||
| 2569 | return () if (! @d); | |||
| 2570 | foreach $d (@d) { | |||
| 2571 | return () if (! _IsInt($d,-31,31) || $d==0); | |||
| 2572 | } | |||
| 2573 | } | |||
| 2574 | ||||
| 2575 | # We need to find years that are a multiple of $n from $y(base) | |||
| 2576 | ($y0)=( _Date_Split($date0, 1) )[0]; | |||
| 2577 | ($y1)=( _Date_Split($date1, 1) )[0]; | |||
| 2578 | if ($dateb) { | |||
| 2579 | ($yb)=( _Date_Split($dateb, 1) )[0]; | |||
| 2580 | } else { | |||
| 2581 | # If $y=1, there is no base year | |||
| 2582 | $yb=0; | |||
| 2583 | } | |||
| 2584 | ||||
| 2585 | @date=(); | |||
| 2586 | for ($yy=$y0; $yy<=$y1; $yy++) { | |||
| 2587 | if (($yy-$yb)%$n == 0) { | |||
| 2588 | foreach $m (@m) { | |||
| 2589 | foreach $d (@d) { | |||
| 2590 | my $dim = Date_DaysInMonth($m,$yy); | |||
| 2591 | my $tmpd = $d; | |||
| 2592 | if ($tmpd < 0) { | |||
| 2593 | $tmpd += ($dim+1); | |||
| 2594 | } | |||
| 2595 | next if (! _IsInt($tmpd,1,$dim)); | |||
| 2596 | $date=_Date_Join($yy,$m,$tmpd,0,0,0); | |||
| 2597 | push(@date,$date); | |||
| 2598 | } | |||
| 2599 | } | |||
| 2600 | } | |||
| 2601 | } | |||
| 2602 | last RECUR; | |||
| 2603 | ||||
| 2604 | } else { | |||
| 2605 | ||||
| 2606 | # Y * M-WOM-DOW-H-MN-S | |||
| 2607 | # Y * M-WOM-0-H-MN-S | |||
| 2608 | return () if (! $dateb && $y != 1); | |||
| 2609 | ||||
| 2610 | @m=_ReturnList($m); | |||
| 2611 | return () if (! @m); | |||
| 2612 | @w=_ReturnList($w); | |||
| 2613 | return () if (! @w); | |||
| 2614 | ||||
| 2615 | if ($d eq "0") { | |||
| 2616 | @d=(1); | |||
| 2617 | } else { | |||
| 2618 | @d=_ReturnList($d); | |||
| 2619 | } | |||
| 2620 | ||||
| 2621 | ($y0)=( _Date_Split($date0, 1) )[0]; | |||
| 2622 | ($y1)=( _Date_Split($date1, 1) )[0]; | |||
| 2623 | if ($dateb) { | |||
| 2624 | ($yb)=( _Date_Split($dateb, 1) )[0]; | |||
| 2625 | } else { | |||
| 2626 | # If $y=1, there is no base year | |||
| 2627 | $yb=0; | |||
| 2628 | } | |||
| 2629 | @y=(); | |||
| 2630 | for ($yy=$y0; $yy<=$y1; $yy++) { | |||
| 2631 | if (($yy-$yb)%$n == 0) { | |||
| 2632 | push(@y,$yy); | |||
| 2633 | } | |||
| 2634 | } | |||
| 2635 | ||||
| 2636 | @date=_Date_Recur_WoM(\@y,\@m,\@w,\@d); | |||
| 2637 | last RECUR; | |||
| 2638 | } | |||
| 2639 | } | |||
| 2640 | ||||
| 2641 | if ($#recur0==1) { | |||
| 2642 | ||||
| 2643 | # Y-M * W-D-H-MN-S | |||
| 2644 | ||||
| 2645 | if ($w eq "0") { | |||
| 2646 | # Y-M * 0-D-H-MN-S => Y-M-0 * D-H-MN-S | |||
| 2647 | push(@recur0,0); | |||
| 2648 | shift(@recur1); | |||
| 2649 | ||||
| 2650 | } elsif ($m==0) { | |||
| 2651 | ||||
| 2652 | # Y-0 * WOY-0-H-MN-S | |||
| 2653 | # Y-0 * WOY-DOW-H-MN-S | |||
| 2654 | return () if (! $dateb && $y != 1); | |||
| 2655 | $n=$y; | |||
| 2656 | $n=1 if ($n==0); | |||
| 2657 | ||||
| 2658 | @w=_ReturnList($w); | |||
| 2659 | return () if (! @w); | |||
| 2660 | foreach $w (@w) { | |||
| 2661 | return () if ($w==0 || ! _IsInt($w,-53,53)); | |||
| 2662 | } | |||
| 2663 | ||||
| 2664 | if ($d eq "0") { | |||
| 2665 | @d=(1); | |||
| 2666 | } else { | |||
| 2667 | @d=_ReturnList($d); | |||
| 2668 | return () if (! @d); | |||
| 2669 | foreach $d (@d) { | |||
| 2670 | $d += 8 if ($d<0); | |||
| 2671 | return () if (! _IsInt($d,1,7)); | |||
| 2672 | } | |||
| 2673 | } | |||
| 2674 | ||||
| 2675 | # We need to find years that are a multiple of $n from $y(base) | |||
| 2676 | ($y0)=( _Date_Split($date0, 1) )[0]; | |||
| 2677 | ($y1)=( _Date_Split($date1, 1) )[0]; | |||
| 2678 | if ($dateb) { | |||
| 2679 | ($yb)=( _Date_Split($dateb, 1) )[0]; | |||
| 2680 | } else { | |||
| 2681 | # If $y=1, there is no base year | |||
| 2682 | $yb=0; | |||
| 2683 | } | |||
| 2684 | ||||
| 2685 | @date=(); | |||
| 2686 | for ($yy=$y0; $yy<=$y1; $yy++) { | |||
| 2687 | if (($yy-$yb)%$n == 0) { | |||
| 2688 | foreach $w (@w) { | |||
| 2689 | foreach $d (@d) { | |||
| 2690 | my($tmpw,$del); | |||
| 2691 | if ($w<0) { | |||
| 2692 | $date="$yy-12-31-00:00:00"; | |||
| 2693 | $tmpw = (-$w)-1; | |||
| 2694 | $del="-0:0:$tmpw:0:0:0:0"; | |||
| 2695 | $date=Date_GetPrev($date,$d,1); | |||
| 2696 | } else { | |||
| 2697 | $date="$yy-01-01-00:00:00"; | |||
| 2698 | $tmpw = ($w)-1; | |||
| 2699 | $del="0:0:$tmpw:0:0:0:0"; | |||
| 2700 | $date=Date_GetNext($date,$d,1); | |||
| 2701 | } | |||
| 2702 | $date=DateCalc($date,$del); | |||
| 2703 | next if ((_Date_Split($date))[0] != $yy); | |||
| 2704 | push(@date,$date); | |||
| 2705 | } | |||
| 2706 | } | |||
| 2707 | } | |||
| 2708 | } | |||
| 2709 | last RECUR; | |||
| 2710 | ||||
| 2711 | } else { | |||
| 2712 | ||||
| 2713 | # Y-M * WOM-0-H-MN-S | |||
| 2714 | # Y-M * WOM-DOW-H-MN-S | |||
| 2715 | return () if (! $dateb && ($y != 0 || $m != 1)); | |||
| 2716 | @tmp=(@recur0); | |||
| 2717 | push(@tmp,0) while ($#tmp<6); | |||
| 2718 | $delta=join(":",@tmp); | |||
| 2719 | $dateb=$date0 if (! $dateb); | |||
| 2720 | @tmp=_Date_Recur($date0,$date1,$dateb,$delta); | |||
| 2721 | ||||
| 2722 | @w=_ReturnList($w); | |||
| 2723 | @m=(); | |||
| 2724 | if ($d eq "0") { | |||
| 2725 | @d=(1); | |||
| 2726 | } else { | |||
| 2727 | @d=_ReturnList($d); | |||
| 2728 | } | |||
| 2729 | ||||
| 2730 | @date=_Date_Recur_WoM(\@tmp,\@m,\@w,\@d); | |||
| 2731 | last RECUR; | |||
| 2732 | } | |||
| 2733 | } | |||
| 2734 | ||||
| 2735 | if ($#recur0==2) { | |||
| 2736 | # Y-M-W * D-H-MN-S | |||
| 2737 | ||||
| 2738 | if ($d eq "0") { | |||
| 2739 | ||||
| 2740 | # Y-M-W * 0-H-MN-S | |||
| 2741 | return () if (! $dateb); | |||
| 2742 | $y=1 if ($y==0 && $m==0 && $w==0); | |||
| 2743 | $delta="$y:$m:$w:0:0:0:0"; | |||
| 2744 | @date=_Date_Recur($date0,$date1,$dateb,$delta); | |||
| 2745 | last RECUR; | |||
| 2746 | ||||
| 2747 | } elsif ($m==0 && $w==0) { | |||
| 2748 | ||||
| 2749 | # Y-0-0 * DOY-H-MN-S | |||
| 2750 | $y=1 if ($y==0); | |||
| 2751 | $n=$y; | |||
| 2752 | return () if (! $dateb && $y!=1); | |||
| 2753 | ||||
| 2754 | @d=_ReturnList($d); | |||
| 2755 | return () if (! @d); | |||
| 2756 | foreach $d (@d) { | |||
| 2757 | return () if (! _IsInt($d,-366,366) || $d==0); | |||
| 2758 | } | |||
| 2759 | ||||
| 2760 | # We need to find years that are a multiple of $n from $y(base) | |||
| 2761 | ($y0)=( _Date_Split($date0, 1) )[0]; | |||
| 2762 | ($y1)=( _Date_Split($date1, 1) )[0]; | |||
| 2763 | if ($dateb) { | |||
| 2764 | ($yb)=( _Date_Split($dateb, 1) )[0]; | |||
| 2765 | } else { | |||
| 2766 | # If $y=1, there is no base year | |||
| 2767 | $yb=0; | |||
| 2768 | } | |||
| 2769 | @date=(); | |||
| 2770 | for ($yy=$y0; $yy<=$y1; $yy++) { | |||
| 2771 | my $diy = Date_DaysInYear($yy); | |||
| 2772 | if (($yy-$yb)%$n == 0) { | |||
| 2773 | foreach $d (@d) { | |||
| 2774 | my $tmpd = $d; | |||
| 2775 | $tmpd += ($diy+1) if ($tmpd<0); | |||
| 2776 | next if (! _IsInt($tmpd,1,$diy)); | |||
| 2777 | ($y,$m,$dd)=Date_NthDayOfYear($yy,$tmpd); | |||
| 2778 | push(@date, _Date_Join($y,$m,$dd,0,0,0)); | |||
| 2779 | } | |||
| 2780 | } | |||
| 2781 | } | |||
| 2782 | last RECUR; | |||
| 2783 | ||||
| 2784 | } elsif ($w>0) { | |||
| 2785 | ||||
| 2786 | # Y-M-W * DOW-H-MN-S | |||
| 2787 | return () if (! $dateb && ($y != 0 && $m != 0 && $w != 1)); | |||
| 2788 | @tmp=(@recur0); | |||
| 2789 | push(@tmp,0) while ($#tmp<6); | |||
| 2790 | $delta=join(":",@tmp); | |||
| 2791 | ||||
| 2792 | @d=_ReturnList($d); | |||
| 2793 | return () if (! @d); | |||
| 2794 | foreach $d (@d) { | |||
| 2795 | $d += 8 if ($d<0); | |||
| 2796 | return () if (! _IsInt($d,1,7)); | |||
| 2797 | } | |||
| 2798 | ||||
| 2799 | # Find out what DofW the basedate is. | |||
| 2800 | $dateb = $date0 if (! $dateb); | |||
| 2801 | @tmp2=_Date_Split($dateb, 1); | |||
| 2802 | $tmp=Date_DayOfWeek($tmp2[1],$tmp2[2],$tmp2[0]); | |||
| 2803 | ||||
| 2804 | @date=(); | |||
| 2805 | foreach $d (@d) { | |||
| 2806 | $date_b=$dateb; | |||
| 2807 | # Move basedate to DOW in the same week | |||
| 2808 | if ($d != $tmp) { | |||
| 2809 | if (($tmp>=$Cnf{"FirstDay"} && $d<$Cnf{"FirstDay"}) || | |||
| 2810 | ($tmp>=$Cnf{"FirstDay"} && $d>$tmp) || | |||
| 2811 | ($tmp<$d && $d<$Cnf{"FirstDay"})) { | |||
| 2812 | $date_b=Date_GetNext($date_b,$d); | |||
| 2813 | } else { | |||
| 2814 | $date_b=Date_GetPrev($date_b,$d); | |||
| 2815 | } | |||
| 2816 | } | |||
| 2817 | push(@date,_Date_Recur($date0,$date1,$date_b,$delta)); | |||
| 2818 | } | |||
| 2819 | last RECUR; | |||
| 2820 | ||||
| 2821 | } elsif ($m>0) { | |||
| 2822 | ||||
| 2823 | # Y-M-0 * DOM-H-MN-S | |||
| 2824 | return () if (! $dateb && ($y != 0 && $m != 1)); | |||
| 2825 | @tmp=(@recur0); | |||
| 2826 | push(@tmp,0) while ($#tmp<6); | |||
| 2827 | $delta=join(":",@tmp); | |||
| 2828 | ||||
| 2829 | @d=_ReturnList($d); | |||
| 2830 | return () if (! @d); | |||
| 2831 | foreach $d (@d) { | |||
| 2832 | return () if ($d==0 || ! _IsInt($d,-31,31)); | |||
| 2833 | } | |||
| 2834 | $dateb = $date0 if (! $dateb); | |||
| 2835 | ||||
| 2836 | @tmp2=_Date_Recur($date0,$date1,$dateb,$delta); | |||
| 2837 | @date=(); | |||
| 2838 | foreach $date (@tmp2) { | |||
| 2839 | ($y,$m)=( _Date_Split($date, 1) )[0..1]; | |||
| 2840 | my $dim=Date_DaysInMonth($m,$y); | |||
| 2841 | foreach $d (@d) { | |||
| 2842 | my $tmpd = $d; | |||
| 2843 | $tmpd += ($dim+1) if ($tmpd<0); | |||
| 2844 | next if (! _IsInt($tmpd,1,$dim)); | |||
| 2845 | push(@date,_Date_Join($y,$m,$tmpd,0,0,0)); | |||
| 2846 | } | |||
| 2847 | } | |||
| 2848 | last RECUR; | |||
| 2849 | ||||
| 2850 | } else { | |||
| 2851 | return (); | |||
| 2852 | } | |||
| 2853 | } | |||
| 2854 | ||||
| 2855 | if ($#recur0>2) { | |||
| 2856 | ||||
| 2857 | # Y-M-W-D * H-MN-S | |||
| 2858 | # Y-M-W-D-H * MN-S | |||
| 2859 | # Y-M-W-D-H-MN * S | |||
| 2860 | # Y-M-W-D-H-S | |||
| 2861 | if (($#recur0 == 3 && | |||
| 2862 | ($y == 0 && $m == 0 && $w == 0 && $d == 1)) || | |||
| 2863 | ($#recur0 == 4 && | |||
| 2864 | ($y == 0 && $m == 0 && $w == 0 && $d == 0 && $h == 1)) || | |||
| 2865 | ($#recur0 == 5 && | |||
| 2866 | ($y == 0 && $m == 0 && $w == 0 && $d == 0 && $h == 0 && | |||
| 2867 | $mn == 1))) { | |||
| 2868 | $dateb = $date0; | |||
| 2869 | } | |||
| 2870 | return () if (! $dateb); | |||
| 2871 | @tmp=(@recur0); | |||
| 2872 | push(@tmp,0) while ($#tmp<6); | |||
| 2873 | $delta=join(":",@tmp); | |||
| 2874 | return () if ($delta !~ /[1-9]/); # return if "0:0:0:0:0:0:0" | |||
| 2875 | @date=_Date_Recur($date0,$date1,$dateb,$delta); | |||
| 2876 | if (@recur1) { | |||
| 2877 | unshift(@recur1,-1) while ($#recur1<2); | |||
| 2878 | @time=@recur1; | |||
| 2879 | } else { | |||
| 2880 | shift(@date); | |||
| 2881 | pop(@date); | |||
| 2882 | @time=(); | |||
| 2883 | } | |||
| 2884 | } | |||
| 2885 | ||||
| 2886 | last RECUR; | |||
| 2887 | } | |||
| 2888 | @date=_Date_RecurSetTime($date0,$date1,\@date,@time) if (@time); | |||
| 2889 | ||||
| 2890 | # | |||
| 2891 | # We've got a list of dates. Operate on them with the flags. | |||
| 2892 | # | |||
| 2893 | ||||
| 2894 | my($sign,$forw,$today,$df,$db,$work,$i); | |||
| 2895 | if (@flags) { | |||
| 2896 | FLAG: foreach $f (@flags) { | |||
| 2897 | $f = uc($f); | |||
| 2898 | ||||
| 2899 | if ($f =~ /^(P|N)(D|T)([1-7])$/) { | |||
| 2900 | @tmp=($1,$2,$3); | |||
| 2901 | $forw =($tmp[0] eq "P" ? 0 : 1); | |||
| 2902 | $today=($tmp[1] eq "D" ? 0 : 1); | |||
| 2903 | $d=$tmp[2]; | |||
| 2904 | @tmp=(); | |||
| 2905 | foreach $date (@date) { | |||
| 2906 | if ($forw) { | |||
| 2907 | push(@tmp, Date_GetNext($date,$d,$today)); | |||
| 2908 | } else { | |||
| 2909 | push(@tmp, Date_GetPrev($date,$d,$today)); | |||
| 2910 | } | |||
| 2911 | } | |||
| 2912 | @date=@tmp; | |||
| 2913 | next FLAG; | |||
| 2914 | } | |||
| 2915 | ||||
| 2916 | # We want to go forward exact amounts of time instead of | |||
| 2917 | # business mode calculations so that we don't change the time | |||
| 2918 | # (which may have been set in the recur). | |||
| 2919 | if ($f =~ /^(F|B)(D|W)(\d+)$/) { | |||
| 2920 | @tmp=($1,$2,$3); | |||
| 2921 | $sign="+"; | |||
| 2922 | $sign="-" if ($tmp[0] eq "B"); | |||
| 2923 | $work=0; | |||
| 2924 | $work=1 if ($tmp[1] eq "W"); | |||
| 2925 | $n=$tmp[2]; | |||
| 2926 | @tmp=(); | |||
| 2927 | foreach $date (@date) { | |||
| 2928 | for ($i=1; $i<=$n; $i++) { | |||
| 2929 | while (1) { | |||
| 2930 | $date=DateCalc($date,"${sign}0:0:0:1:0:0:0"); | |||
| 2931 | last if (! $work || Date_IsWorkDay($date,0)); | |||
| 2932 | } | |||
| 2933 | } | |||
| 2934 | push(@tmp,$date); | |||
| 2935 | } | |||
| 2936 | @date=@tmp; | |||
| 2937 | next FLAG; | |||
| 2938 | } | |||
| 2939 | ||||
| 2940 | if ($f =~ /^CW(N|P|D)$/ || $f =~ /^(N|P|D)W(D)$/) { | |||
| 2941 | $tmp=$1; | |||
| 2942 | my $noalt = $2 ? 1 : 0; | |||
| 2943 | if ($tmp eq "N" || ($tmp eq "D" && $Cnf{"TomorrowFirst"})) { | |||
| 2944 | $forw=1; | |||
| 2945 | } else { | |||
| 2946 | $forw=0; | |||
| 2947 | } | |||
| 2948 | ||||
| 2949 | @tmp=(); | |||
| 2950 | DATE: foreach $date (@date) { | |||
| 2951 | $df=$db=$date; | |||
| 2952 | if (Date_IsWorkDay($date)) { | |||
| 2953 | push(@tmp,$date); | |||
| 2954 | next DATE; | |||
| 2955 | } | |||
| 2956 | while (1) { | |||
| 2957 | if ($forw) { | |||
| 2958 | $d=$df=DateCalc($df,"+0:0:0:1:0:0:0"); | |||
| 2959 | } else { | |||
| 2960 | $d=$db=DateCalc($db,"-0:0:0:1:0:0:0"); | |||
| 2961 | } | |||
| 2962 | if (Date_IsWorkDay($d)) { | |||
| 2963 | push(@tmp,$d); | |||
| 2964 | next DATE; | |||
| 2965 | } | |||
| 2966 | $forw=1-$forw if (! $noalt); | |||
| 2967 | } | |||
| 2968 | } | |||
| 2969 | @date=@tmp; | |||
| 2970 | next FLAG; | |||
| 2971 | } | |||
| 2972 | ||||
| 2973 | if ($f eq "EASTER") { | |||
| 2974 | @tmp=(); | |||
| 2975 | foreach $date (@date) { | |||
| 2976 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date, 1); | |||
| 2977 | ($m,$d)=_Date_Easter($y); | |||
| 2978 | $date=_Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 2979 | next if (Date_Cmp($date,$date0)<0 || | |||
| 2980 | Date_Cmp($date,$date1)>0); | |||
| 2981 | push(@tmp,$date); | |||
| 2982 | } | |||
| 2983 | @date=@tmp; | |||
| 2984 | } | |||
| 2985 | } | |||
| 2986 | } | |||
| 2987 | ||||
| 2988 | @date = sort { Date_Cmp($a,$b) } @date; | |||
| 2989 | return @date; | |||
| 2990 | } | |||
| 2991 | ||||
| 2992 | sub Date_GetPrev { | |||
| 2993 | print "DEBUG: Date_GetPrev\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 2994 | my($date,$dow,$today,$hr,$min,$sec)=@_; | |||
| 2995 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 2996 | my($y,$m,$d,$h,$mn,$s,$err,$curr_dow,%dow,$num,$delta,$th,$tm,$ts, | |||
| 2997 | $adjust,$curr)=(); | |||
| 2998 | $hr="00" if (defined $hr && $hr eq "0"); | |||
| 2999 | $min="00" if (defined $min && $min eq "0"); | |||
| 3000 | $sec="00" if (defined $sec && $sec eq "0"); | |||
| 3001 | ||||
| 3002 | if (! _Date_Split($date)) { | |||
| 3003 | $date=ParseDateString($date); | |||
| 3004 | return "" if (! $date); | |||
| 3005 | } | |||
| 3006 | $curr=$date; | |||
| 3007 | ($y,$m,$d)=( _Date_Split($date, 1) )[0..2]; | |||
| 3008 | ||||
| 3009 | if ($dow) { | |||
| 3010 | $curr_dow=Date_DayOfWeek($m,$d,$y); | |||
| 3011 | %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} }; | |||
| 3012 | if (_IsInt($dow)) { | |||
| 3013 | return "" if ($dow<1 || $dow>7); | |||
| 3014 | } else { | |||
| 3015 | return "" if (! exists $dow{lc($dow)}); | |||
| 3016 | $dow=$dow{lc($dow)}; | |||
| 3017 | } | |||
| 3018 | if ($dow == $curr_dow) { | |||
| 3019 | $date=_DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0) if (! $today); | |||
| 3020 | $adjust=1 if ($today==2); | |||
| 3021 | } else { | |||
| 3022 | $dow -= 7 if ($dow>$curr_dow); # make sure previous day is less | |||
| 3023 | $num = $curr_dow - $dow; | |||
| 3024 | $date=_DateCalc_DateDelta($date,"-0:0:0:$num:0:0:0",\$err,0); | |||
| 3025 | } | |||
| 3026 | $date=Date_SetTime($date,$hr,$min,$sec) if (defined $hr); | |||
| 3027 | $date=_DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0) | |||
| 3028 | if ($adjust && Date_Cmp($date,$curr)>0); | |||
| 3029 | ||||
| 3030 | } else { | |||
| 3031 | ($h,$mn,$s)=( _Date_Split($date, 1) )[3..5]; | |||
| 3032 | ($th,$tm,$ts)=_Date_ParseTime($hr,$min,$sec); | |||
| 3033 | if ($hr) { | |||
| 3034 | ($hr,$min,$sec)=($th,$tm,$ts); | |||
| 3035 | $delta="-0:0:0:1:0:0:0"; | |||
| 3036 | } elsif ($min) { | |||
| 3037 | ($hr,$min,$sec)=($h,$tm,$ts); | |||
| 3038 | $delta="-0:0:0:0:1:0:0"; | |||
| 3039 | } elsif ($sec) { | |||
| 3040 | ($hr,$min,$sec)=($h,$mn,$ts); | |||
| 3041 | $delta="-0:0:0:0:0:1:0"; | |||
| 3042 | } else { | |||
| 3043 | confess "ERROR: invalid arguments in Date_GetPrev.\n"; | |||
| 3044 | } | |||
| 3045 | ||||
| 3046 | $d=Date_SetTime($date,$hr,$min,$sec); | |||
| 3047 | if ($today) { | |||
| 3048 | $d=_DateCalc_DateDelta($d,$delta,\$err,0) if (Date_Cmp($d,$date)>0); | |||
| 3049 | } else { | |||
| 3050 | $d=_DateCalc_DateDelta($d,$delta,\$err,0) if (Date_Cmp($d,$date)>=0); | |||
| 3051 | } | |||
| 3052 | $date=$d; | |||
| 3053 | } | |||
| 3054 | return $date; | |||
| 3055 | } | |||
| 3056 | ||||
| 3057 | sub Date_GetNext { | |||
| 3058 | print "DEBUG: Date_GetNext\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3059 | my($date,$dow,$today,$hr,$min,$sec)=@_; | |||
| 3060 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3061 | my($y,$m,$d,$h,$mn,$s,$err,$curr_dow,%dow,$num,$delta,$th,$tm,$ts, | |||
| 3062 | $adjust,$curr)=(); | |||
| 3063 | $hr="00" if (defined $hr && $hr eq "0"); | |||
| 3064 | $min="00" if (defined $min && $min eq "0"); | |||
| 3065 | $sec="00" if (defined $sec && $sec eq "0"); | |||
| 3066 | ||||
| 3067 | if (! _Date_Split($date)) { | |||
| 3068 | $date=ParseDateString($date); | |||
| 3069 | return "" if (! $date); | |||
| 3070 | } | |||
| 3071 | $curr=$date; | |||
| 3072 | ($y,$m,$d)=( _Date_Split($date, 1) )[0..2]; | |||
| 3073 | ||||
| 3074 | if ($dow) { | |||
| 3075 | $curr_dow=Date_DayOfWeek($m,$d,$y); | |||
| 3076 | %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} }; | |||
| 3077 | if (_IsInt($dow)) { | |||
| 3078 | return "" if ($dow<1 || $dow>7); | |||
| 3079 | } else { | |||
| 3080 | return "" if (! exists $dow{lc($dow)}); | |||
| 3081 | $dow=$dow{lc($dow)}; | |||
| 3082 | } | |||
| 3083 | if ($dow == $curr_dow) { | |||
| 3084 | $date=_DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0) if (! $today); | |||
| 3085 | $adjust=1 if ($today==2); | |||
| 3086 | } else { | |||
| 3087 | $curr_dow -= 7 if ($curr_dow>$dow); # make sure next date is greater | |||
| 3088 | $num = $dow - $curr_dow; | |||
| 3089 | $date=_DateCalc_DateDelta($date,"+0:0:0:$num:0:0:0",\$err,0); | |||
| 3090 | } | |||
| 3091 | $date=Date_SetTime($date,$hr,$min,$sec) if (defined $hr); | |||
| 3092 | $date=_DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0) | |||
| 3093 | if ($adjust && Date_Cmp($date,$curr)<0); | |||
| 3094 | ||||
| 3095 | } else { | |||
| 3096 | ($h,$mn,$s)=( _Date_Split($date, 1) )[3..5]; | |||
| 3097 | ($th,$tm,$ts)=_Date_ParseTime($hr,$min,$sec); | |||
| 3098 | if ($hr) { | |||
| 3099 | ($hr,$min,$sec)=($th,$tm,$ts); | |||
| 3100 | $delta="+0:0:0:1:0:0:0"; | |||
| 3101 | } elsif ($min) { | |||
| 3102 | ($hr,$min,$sec)=($h,$tm,$ts); | |||
| 3103 | $delta="+0:0:0:0:1:0:0"; | |||
| 3104 | } elsif ($sec) { | |||
| 3105 | ($hr,$min,$sec)=($h,$mn,$ts); | |||
| 3106 | $delta="+0:0:0:0:0:1:0"; | |||
| 3107 | } else { | |||
| 3108 | confess "ERROR: invalid arguments in Date_GetNext.\n"; | |||
| 3109 | } | |||
| 3110 | ||||
| 3111 | $d=Date_SetTime($date,$hr,$min,$sec); | |||
| 3112 | if ($today) { | |||
| 3113 | $d=_DateCalc_DateDelta($d,$delta,\$err,0) if (Date_Cmp($d,$date)<0); | |||
| 3114 | } else { | |||
| 3115 | $d=_DateCalc_DateDelta($d,$delta,\$err,0) if (Date_Cmp($d,$date)<1); | |||
| 3116 | } | |||
| 3117 | $date=$d; | |||
| 3118 | } | |||
| 3119 | ||||
| 3120 | return $date; | |||
| 3121 | } | |||
| 3122 | ||||
| 3123 | sub Date_IsHoliday { | |||
| 3124 | print "DEBUG: Date_IsHoliday\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3125 | my($date)=@_; | |||
| 3126 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3127 | $date=ParseDateString($date); | |||
| 3128 | return undef if (! $date); | |||
| 3129 | $date=Date_SetTime($date,0,0,0); | |||
| 3130 | my($y)=(_Date_Split($date, 1))[0]; | |||
| 3131 | _Date_UpdateHolidays($y) if (! exists $Holiday{"dates"}{$y}); | |||
| 3132 | return undef if (! exists $Holiday{"dates"}{$y}{$date}); | |||
| 3133 | my($name)=$Holiday{"dates"}{$y}{$date}; | |||
| 3134 | return "" if (! $name); | |||
| 3135 | $name; | |||
| 3136 | } | |||
| 3137 | ||||
| 3138 | sub Events_List { | |||
| 3139 | print "DEBUG: Events_List\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3140 | my(@args)=@_; | |||
| 3141 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3142 | _Events_ParseRaw(); | |||
| 3143 | ||||
| 3144 | my($tmp,$date0,$date1,$flag); | |||
| 3145 | $date0=ParseDateString($args[0]); | |||
| 3146 | warn "Invalid date $args[0]", return undef if (! $date0); | |||
| 3147 | ||||
| 3148 | if ($#args == 0) { | |||
| 3149 | return _Events_Calc($date0); | |||
| 3150 | } | |||
| 3151 | ||||
| 3152 | if ($args[1]) { | |||
| 3153 | $date1=ParseDateString($args[1]); | |||
| 3154 | warn "Invalid date $args[1]\n", return undef if (! $date1); | |||
| 3155 | if (Date_Cmp($date0,$date1)>0) { | |||
| 3156 | $tmp=$date1; | |||
| 3157 | $date1=$date0; | |||
| 3158 | $date0=$tmp; | |||
| 3159 | } | |||
| 3160 | } else { | |||
| 3161 | $date0=Date_SetTime($date0,"00:00:00"); | |||
| 3162 | $date1=_DateCalc_DateDelta($date0,"+0:0:0:1:0:0:0"); | |||
| 3163 | } | |||
| 3164 | ||||
| 3165 | $tmp=_Events_Calc($date0,$date1); | |||
| 3166 | ||||
| 3167 | $flag=$args[2]; | |||
| 3168 | return $tmp if (! $flag); | |||
| 3169 | ||||
| 3170 | my(@tmp,%ret,$delta)=(); | |||
| 3171 | @tmp=@$tmp; | |||
| 3172 | push(@tmp,$date1); | |||
| 3173 | ||||
| 3174 | if ($flag==1) { | |||
| 3175 | while ($#tmp>0) { | |||
| 3176 | ($date0,$tmp)=splice(@tmp,0,2); | |||
| 3177 | $date1=$tmp[0]; | |||
| 3178 | $delta=_DateCalc_DateDate($date0,$date1); | |||
| 3179 | foreach $flag (@$tmp) { | |||
| 3180 | if (exists $ret{$flag}) { | |||
| 3181 | $ret{$flag}=_DateCalc_DeltaDelta($ret{$flag},$delta); | |||
| 3182 | } else { | |||
| 3183 | $ret{$flag}=$delta; | |||
| 3184 | } | |||
| 3185 | } | |||
| 3186 | } | |||
| 3187 | return \%ret; | |||
| 3188 | ||||
| 3189 | } elsif ($flag==2) { | |||
| 3190 | while ($#tmp>0) { | |||
| 3191 | ($date0,$tmp)=splice(@tmp,0,2); | |||
| 3192 | $date1=$tmp[0]; | |||
| 3193 | $delta=_DateCalc_DateDate($date0,$date1); | |||
| 3194 | $flag=join("+",sort { Date_Cmp($a,$b) } @$tmp); | |||
| 3195 | next if (! $flag); | |||
| 3196 | if (exists $ret{$flag}) { | |||
| 3197 | $ret{$flag}=_DateCalc_DeltaDelta($ret{$flag},$delta); | |||
| 3198 | } else { | |||
| 3199 | $ret{$flag}=$delta; | |||
| 3200 | } | |||
| 3201 | } | |||
| 3202 | return \%ret; | |||
| 3203 | } | |||
| 3204 | ||||
| 3205 | warn "Invalid flag $flag\n"; | |||
| 3206 | return undef; | |||
| 3207 | } | |||
| 3208 | ||||
| 3209 | ### | |||
| 3210 | # NOTE: The following routines may be called in the routines below with very | |||
| 3211 | # little time penalty. | |||
| 3212 | ### | |||
| 3213 | sub Date_SetTime { | |||
| 3214 | print "DEBUG: Date_SetTime\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3215 | my($date,$h,$mn,$s)=@_; | |||
| 3216 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3217 | my($y,$m,$d)=(); | |||
| 3218 | ||||
| 3219 | if (! _Date_Split($date)) { | |||
| 3220 | $date=ParseDateString($date); | |||
| 3221 | return "" if (! $date); | |||
| 3222 | } | |||
| 3223 | ||||
| 3224 | ($y,$m,$d)=( _Date_Split($date, 1) )[0..2]; | |||
| 3225 | ($h,$mn,$s)=_Date_ParseTime($h,$mn,$s); | |||
| 3226 | ||||
| 3227 | my($ampm,$wk); | |||
| 3228 | return "" if (_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk)); | |||
| 3229 | _Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 3230 | } | |||
| 3231 | ||||
| 3232 | sub Date_SetDateField { | |||
| 3233 | print "DEBUG: Date_SetDateField\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3234 | my($date,$field,$val,$nocheck)=@_; | |||
| 3235 | my($y,$m,$d,$h,$mn,$s)=(); | |||
| 3236 | $nocheck=0 if (! defined $nocheck); | |||
| 3237 | ||||
| 3238 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date); | |||
| 3239 | ||||
| 3240 | if (! $y) { | |||
| 3241 | $date=ParseDateString($date); | |||
| 3242 | return "" if (! $date); | |||
| 3243 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date, 1); | |||
| 3244 | } | |||
| 3245 | ||||
| 3246 | if (lc($field) eq "y") { | |||
| 3247 | $y=$val; | |||
| 3248 | } elsif (lc($field) eq "m") { | |||
| 3249 | $m=$val; | |||
| 3250 | } elsif (lc($field) eq "d") { | |||
| 3251 | $d=$val; | |||
| 3252 | } elsif (lc($field) eq "h") { | |||
| 3253 | $h=$val; | |||
| 3254 | } elsif (lc($field) eq "mn") { | |||
| 3255 | $mn=$val; | |||
| 3256 | } elsif (lc($field) eq "s") { | |||
| 3257 | $s=$val; | |||
| 3258 | } else { | |||
| 3259 | confess "ERROR: Date_SetDateField: invalid field: $field\n"; | |||
| 3260 | } | |||
| 3261 | ||||
| 3262 | $date=_Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 3263 | return $date if ($nocheck || _Date_Split($date)); | |||
| 3264 | return ""; | |||
| 3265 | } | |||
| 3266 | ||||
| 3267 | ######################################################################## | |||
| 3268 | # OTHER SUBROUTINES | |||
| 3269 | ######################################################################## | |||
| 3270 | # NOTE: These routines should not call any of the routines above as | |||
| 3271 | # there will be a severe time penalty (and the possibility of | |||
| 3272 | # infinite recursion). The last couple routines above are | |||
| 3273 | # exceptions. | |||
| 3274 | # NOTE: Date_Init is a special case. It should be called (conditionally) | |||
| 3275 | # in every routine that uses any variable from the Date::Manip | |||
| 3276 | # namespace. | |||
| 3277 | ######################################################################## | |||
| 3278 | ||||
| 3279 | sub Date_DaysInMonth { | |||
| 3280 | print "DEBUG: Date_DaysInMonth\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3281 | my($m,$y)=@_; | |||
| 3282 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3283 | my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 3284 | $d_in_m[2]=29 if (Date_LeapYear($y)); | |||
| 3285 | return $d_in_m[$m]; | |||
| 3286 | } | |||
| 3287 | ||||
| 3288 | sub Date_DayOfWeek { | |||
| 3289 | print "DEBUG: Date_DayOfWeek\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3290 | my($m,$d,$y)=@_; | |||
| 3291 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3292 | my($dayofweek,$dec31)=(); | |||
| 3293 | ||||
| 3294 | $dec31=5; # Dec 31, 1BC was Friday | |||
| 3295 | $dayofweek=(Date_DaysSince1BC($m,$d,$y)+$dec31) % 7; | |||
| 3296 | $dayofweek=7 if ($dayofweek==0); | |||
| 3297 | return $dayofweek; | |||
| 3298 | } | |||
| 3299 | ||||
| 3300 | # Can't be in "use integer" because the numbers are too big. | |||
| 3301 | 3 | 374µs | 125µs | no integer; # spent 15µs making 1 call to integer::unimport |
| 3302 | sub Date_SecsSince1970 { | |||
| 3303 | print "DEBUG: Date_SecsSince1970\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3304 | my($m,$d,$y,$h,$mn,$s)=@_; | |||
| 3305 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3306 | my($sec_now,$sec_70)=(); | |||
| 3307 | $sec_now=(Date_DaysSince1BC($m,$d,$y)-1)*24*3600 + $h*3600 + $mn*60 + $s; | |||
| 3308 | # $sec_70 =(Date_DaysSince1BC(1,1,1970)-1)*24*3600; | |||
| 3309 | $sec_70 =62167219200; | |||
| 3310 | return ($sec_now-$sec_70); | |||
| 3311 | } | |||
| 3312 | ||||
| 3313 | sub Date_SecsSince1970GMT { | |||
| 3314 | print "DEBUG: Date_SecsSince1970GMT\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3315 | my($m,$d,$y,$h,$mn,$s)=@_; | |||
| 3316 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3317 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3318 | ||||
| 3319 | my($sec)=Date_SecsSince1970($m,$d,$y,$h,$mn,$s); | |||
| 3320 | return $sec if ($Cnf{"ConvTZ"} eq "IGNORE"); | |||
| 3321 | ||||
| 3322 | my($tz)=$Cnf{"ConvTZ"}; | |||
| 3323 | $tz=$Cnf{"TZ"} if (! $tz); | |||
| 3324 | $tz=$Zone{"n2o"}{lc($tz)} if ($tz !~ /^[+-]\d{4}$/); | |||
| 3325 | ||||
| 3326 | my($tzs)=1; | |||
| 3327 | $tzs=-1 if ($tz<0); | |||
| 3328 | $tz=~/.(..)(..)/; | |||
| 3329 | my($tzh,$tzm)=($1,$2); | |||
| 3330 | $sec - $tzs*($tzh*3600+$tzm*60); | |||
| 3331 | } | |||
| 3332 | 3 | 3.18ms | 1.06ms | use integer; # spent 8µs making 1 call to integer::import |
| 3333 | ||||
| 3334 | sub Date_DaysSince1BC { | |||
| 3335 | print "DEBUG: Date_DaysSince1BC\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3336 | my($m,$d,$y)=@_; | |||
| 3337 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3338 | my($Ny,$N4,$N100,$N400,$dayofyear,$days)=(); | |||
| 3339 | my($cc,$yy)=(); | |||
| 3340 | ||||
| 3341 | $y=~ /(\d{2})(\d{2})/; | |||
| 3342 | ($cc,$yy)=($1,$2); | |||
| 3343 | ||||
| 3344 | # Number of full years since Dec 31, 1BC (counting the year 0000). | |||
| 3345 | $Ny=$y; | |||
| 3346 | ||||
| 3347 | # Number of full 4th years (incl. 0000) since Dec 31, 1BC | |||
| 3348 | $N4=($Ny-1)/4 + 1; | |||
| 3349 | $N4=0 if ($y==0); | |||
| 3350 | ||||
| 3351 | # Number of full 100th years (incl. 0000) | |||
| 3352 | $N100=$cc + 1; | |||
| 3353 | $N100-- if ($yy==0); | |||
| 3354 | $N100=0 if ($y==0); | |||
| 3355 | ||||
| 3356 | # Number of full 400th years (incl. 0000) | |||
| 3357 | $N400=($N100-1)/4 + 1; | |||
| 3358 | $N400=0 if ($y==0); | |||
| 3359 | ||||
| 3360 | $dayofyear=Date_DayOfYear($m,$d,$y); | |||
| 3361 | $days= $Ny*365 + $N4 - $N100 + $N400 + $dayofyear; | |||
| 3362 | ||||
| 3363 | return $days; | |||
| 3364 | } | |||
| 3365 | ||||
| 3366 | sub Date_DayOfYear { | |||
| 3367 | print "DEBUG: Date_DayOfYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3368 | my($m,$d,$y)=@_; | |||
| 3369 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3370 | # DinM = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) | |||
| 3371 | my(@days) = ( 0, 31, 59, 90,120,151,181,212,243,273,304,334,365); | |||
| 3372 | my($ly)=0; | |||
| 3373 | $ly=1 if ($m>2 && Date_LeapYear($y)); | |||
| 3374 | return ($days[$m-1]+$d+$ly); | |||
| 3375 | } | |||
| 3376 | ||||
| 3377 | sub Date_DaysInYear { | |||
| 3378 | print "DEBUG: Date_DaysInYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3379 | my($y)=@_; | |||
| 3380 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3381 | return 366 if (Date_LeapYear($y)); | |||
| 3382 | return 365; | |||
| 3383 | } | |||
| 3384 | ||||
| 3385 | sub Date_WeekOfYear { | |||
| 3386 | print "DEBUG: Date_WeekOfYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3387 | my($m,$d,$y,$f)=@_; | |||
| 3388 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3389 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3390 | ||||
| 3391 | my($day,$dow,$doy)=(); | |||
| 3392 | $doy=Date_DayOfYear($m,$d,$y); | |||
| 3393 | ||||
| 3394 | # The current DayOfYear and DayOfWeek | |||
| 3395 | if ($Cnf{"Jan1Week1"}) { | |||
| 3396 | $day=1; | |||
| 3397 | } else { | |||
| 3398 | $day=4; | |||
| 3399 | } | |||
| 3400 | $dow=Date_DayOfWeek(1,$day,$y); | |||
| 3401 | ||||
| 3402 | # Move back to the first day of week 1. | |||
| 3403 | $f-=7 if ($f>$dow); | |||
| 3404 | $day-= ($dow-$f); | |||
| 3405 | ||||
| 3406 | return 0 if ($day>$doy); # Day is in last week of previous year | |||
| 3407 | return (($doy-$day)/7 + 1); | |||
| 3408 | } | |||
| 3409 | ||||
| 3410 | sub Date_LeapYear { | |||
| 3411 | print "DEBUG: Date_LeapYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3412 | my($y)=@_; | |||
| 3413 | $y=_Date_FixYear($y) if (length($y)!=4); | |||
| 3414 | return 0 unless $y % 4 == 0; | |||
| 3415 | return 1 unless $y % 100 == 0; | |||
| 3416 | return 0 unless $y % 400 == 0; | |||
| 3417 | return 1; | |||
| 3418 | } | |||
| 3419 | ||||
| 3420 | sub Date_DaySuffix { | |||
| 3421 | print "DEBUG: Date_DaySuffix\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3422 | my($d)=@_; | |||
| 3423 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3424 | return $Lang{$Cnf{"Language"}}{"DoML"}[$d-1]; | |||
| 3425 | } | |||
| 3426 | ||||
| 3427 | sub Date_ConvTZ { | |||
| 3428 | print "DEBUG: Date_ConvTZ\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3429 | my($date,$from,$to,$level)=@_; | |||
| 3430 | if (not _Date_Split($date)) { | |||
| 3431 | my $err = "date passed in ('$date') is not a Date::Manip object"; | |||
| 3432 | if (! $level) { | |||
| 3433 | croak $err; | |||
| 3434 | } elsif ($level==1) { | |||
| 3435 | carp $err; | |||
| 3436 | } | |||
| 3437 | return ""; | |||
| 3438 | } | |||
| 3439 | ||||
| 3440 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3441 | my($gmt)=(); | |||
| 3442 | ||||
| 3443 | if (! $from) { | |||
| 3444 | ||||
| 3445 | if (! $to) { | |||
| 3446 | # TZ -> ConvTZ | |||
| 3447 | return $date if ($Cnf{"ConvTZ"} eq "IGNORE" or ! $Cnf{"ConvTZ"}); | |||
| 3448 | $from=$Cnf{"TZ"}; | |||
| 3449 | $to=$Cnf{"ConvTZ"}; | |||
| 3450 | ||||
| 3451 | } else { | |||
| 3452 | # ConvTZ,TZ -> $to | |||
| 3453 | $from=$Cnf{"ConvTZ"}; | |||
| 3454 | $from=$Cnf{"TZ"} if (! $from); | |||
| 3455 | } | |||
| 3456 | ||||
| 3457 | } else { | |||
| 3458 | ||||
| 3459 | if (! $to) { | |||
| 3460 | # $from -> ConvTZ,TZ | |||
| 3461 | return $date if ($Cnf{"ConvTZ"} eq "IGNORE"); | |||
| 3462 | $to=$Cnf{"ConvTZ"}; | |||
| 3463 | $to=$Cnf{"TZ"} if (! $to); | |||
| 3464 | ||||
| 3465 | } else { | |||
| 3466 | # $from -> $to | |||
| 3467 | } | |||
| 3468 | } | |||
| 3469 | ||||
| 3470 | $to=$Zone{"n2o"}{lc($to)} | |||
| 3471 | if (exists $Zone{"n2o"}{lc($to)}); | |||
| 3472 | $from=$Zone{"n2o"}{lc($from)} | |||
| 3473 | if (exists $Zone{"n2o"}{lc($from)}); | |||
| 3474 | $gmt=$Zone{"n2o"}{"gmt"}; | |||
| 3475 | ||||
| 3476 | return $date if ($from !~ /^[+-]\d{4}$/ or $to !~ /^[+-]\d{4}$/); | |||
| 3477 | return $date if ($from eq $to); | |||
| 3478 | ||||
| 3479 | my($s1,$h1,$m1,$s2,$h2,$m2,$d,$h,$m,$sign,$delta,$err,$yr,$mon,$sec)=(); | |||
| 3480 | # We're going to try to do the calculation without calling DateCalc. | |||
| 3481 | ($yr,$mon,$d,$h,$m,$sec)=_Date_Split($date, 1); | |||
| 3482 | ||||
| 3483 | # Convert $date from $from to GMT | |||
| 3484 | $from=~/([+-])(\d{2})(\d{2})/; | |||
| 3485 | ($s1,$h1,$m1)=($1,$2,$3); | |||
| 3486 | $s1= ($s1 eq "-" ? "+" : "-"); # switch sign | |||
| 3487 | $sign=$s1 . "1"; # + or - 1 | |||
| 3488 | ||||
| 3489 | # and from GMT to $to | |||
| 3490 | $to=~/([+-])(\d{2})(\d{2})/; | |||
| 3491 | ($s2,$h2,$m2)=($1,$2,$3); | |||
| 3492 | ||||
| 3493 | if ($s1 eq $s2) { | |||
| 3494 | # Both the same sign | |||
| 3495 | $m+= $sign*($m1+$m2); | |||
| 3496 | $h+= $sign*($h1+$h2); | |||
| 3497 | } else { | |||
| 3498 | $sign=($s2 eq "-" ? +1 : -1) if ($h1<$h2 || ($h1==$h2 && $m1<$m2)); | |||
| 3499 | $m+= $sign*($m1-$m2); | |||
| 3500 | $h+= $sign*($h1-$h2); | |||
| 3501 | } | |||
| 3502 | ||||
| 3503 | if ($m>59) { | |||
| 3504 | $h+= $m/60; | |||
| 3505 | $m-= ($m/60)*60; | |||
| 3506 | } elsif ($m<0) { | |||
| 3507 | $h+= ($m/60 - 1); | |||
| 3508 | $m-= ($m/60 - 1)*60; | |||
| 3509 | } | |||
| 3510 | ||||
| 3511 | if ($h>23) { | |||
| 3512 | $delta=$h/24; | |||
| 3513 | $h -= $delta*24; | |||
| 3514 | if (($d + $delta) > 28) { | |||
| 3515 | $date=_Date_Join($yr,$mon,$d,$h,$m,$sec); | |||
| 3516 | return _DateCalc_DateDelta($date,"+0:0:0:$delta:0:0:0",\$err,0); | |||
| 3517 | } | |||
| 3518 | $d+= $delta; | |||
| 3519 | } elsif ($h<0) { | |||
| 3520 | $delta=-$h/24 + 1; | |||
| 3521 | $h += $delta*24; | |||
| 3522 | if (($d - $delta) < 1) { | |||
| 3523 | $date=_Date_Join($yr,$mon,$d,$h,$m,$sec); | |||
| 3524 | return _DateCalc_DateDelta($date,"-0:0:0:$delta:0:0:0",\$err,0); | |||
| 3525 | } | |||
| 3526 | $d-= $delta; | |||
| 3527 | } | |||
| 3528 | return _Date_Join($yr,$mon,$d,$h,$m,$sec); | |||
| 3529 | } | |||
| 3530 | ||||
| 3531 | sub Date_TimeZone { | |||
| 3532 | print "DEBUG: Date_TimeZone\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3533 | my($null,$tz,@tz,$std,$dst,$time,$isdst,$tmp,$in)=(); | |||
| 3534 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3535 | ||||
| 3536 | # Get timezones from all of the relevant places | |||
| 3537 | ||||
| 3538 | push(@tz,$Cnf{"TZ"}) if (defined $Cnf{"TZ"}); # TZ config var | |||
| 3539 | push(@tz,$ENV{"TZ"}) if (defined $ENV{"TZ"}); # TZ environ var | |||
| 3540 | push(@tz,$ENV{'SYS$TIMEZONE_RULE'}) | |||
| 3541 | if defined $ENV{'SYS$TIMEZONE_RULE'}; # VMS TZ environ var | |||
| 3542 | push(@tz,$ENV{'SYS$TIMEZONE_NAME'}) | |||
| 3543 | if defined $ENV{'SYS$TIMEZONE_NAME'}; # VMS TZ name environ var | |||
| 3544 | push(@tz,$ENV{'UCX$TZ'}) | |||
| 3545 | if defined $ENV{'UCX$TZ'}; # VMS TZ environ var | |||
| 3546 | push(@tz,$ENV{'TCPIP$TZ'}) | |||
| 3547 | if defined $ENV{'TCPIP$TZ'}; # VMS TZ environ var | |||
| 3548 | ||||
| 3549 | # The `date` command... if we're doing taint checking, we need to | |||
| 3550 | # always call it with a full path... otherwise, use the user's path. | |||
| 3551 | # | |||
| 3552 | # Microsoft operating systems don't have a date command built in. Try | |||
| 3553 | # to trap all the various ways of knowing we are on one of these systems. | |||
| 3554 | # | |||
| 3555 | # We'll try `date +%Z` first, and if that fails, we'll take just the | |||
| 3556 | # `date` program and assume the output is of the format: | |||
| 3557 | # Thu Aug 31 14:57:46 EDT 2000 | |||
| 3558 | ||||
| 3559 | unless (($^O ne 'cygwin' && $^X =~ /perl\.exe$/i) or | |||
| 3560 | ($OS eq "Windows") or | |||
| 3561 | ($OS eq "Netware") or | |||
| 3562 | ($OS eq "VMS")) { | |||
| 3563 | if ($Date::Manip::NoTaint) { | |||
| 3564 | if ($OS eq "VMS") { | |||
| 3565 | $tz=$ENV{'SYS$TIMEZONE_NAME'}; | |||
| 3566 | if (! $tz) { | |||
| 3567 | $tz=$ENV{'MULTINET_TIMEZONE'}; | |||
| 3568 | if (! $tz) { | |||
| 3569 | $tz=$ENV{'SYS$TIMEZONE_DIFFERENTIAL'}/3600.; # e.g. '-4' for EDT | |||
| 3570 | } | |||
| 3571 | } | |||
| 3572 | } else { | |||
| 3573 | $tz=`date +%Z 2> /dev/null`; | |||
| 3574 | chomp($tz); | |||
| 3575 | if (! $tz) { | |||
| 3576 | $tz=`date 2> /dev/null`; | |||
| 3577 | chomp($tz); | |||
| 3578 | $tz=(split(/\s+/,$tz))[4]; | |||
| 3579 | } | |||
| 3580 | } | |||
| 3581 | push(@tz,$tz) if (defined $tz); | |||
| 3582 | } else { | |||
| 3583 | # We need to satisfy taint checking, but also look in all the | |||
| 3584 | # directories in @DatePath. | |||
| 3585 | # | |||
| 3586 | local $ENV{PATH} = join(':', @Date::Manip::DatePath); | |||
| 3587 | local $ENV{BASH_ENV} = ''; | |||
| 3588 | $tz=`date +%Z 2> /dev/null`; | |||
| 3589 | chomp($tz); | |||
| 3590 | if (! $tz) { | |||
| 3591 | $tz=`date 2> /dev/null`; | |||
| 3592 | chomp($tz); | |||
| 3593 | $tz=(split(/\s+/,$tz))[4]; | |||
| 3594 | } | |||
| 3595 | push(@tz,$tz) if (defined $tz); | |||
| 3596 | } | |||
| 3597 | } | |||
| 3598 | ||||
| 3599 | push(@tz,$main::TZ) if (defined $main::TZ); # $main::TZ | |||
| 3600 | ||||
| 3601 | if (-s "/etc/TIMEZONE") { # /etc/TIMEZONE | |||
| 3602 | $in=new IO::File; | |||
| 3603 | $in->open("/etc/TIMEZONE","r"); | |||
| 3604 | while (! eof($in)) { | |||
| 3605 | $tmp=<$in>; | |||
| 3606 | if ($tmp =~ /^TZ\s*=\s*(.*?)\s*$/) { | |||
| 3607 | push(@tz,$1); | |||
| 3608 | last; | |||
| 3609 | } | |||
| 3610 | } | |||
| 3611 | $in->close; | |||
| 3612 | } | |||
| 3613 | ||||
| 3614 | if (-s "/etc/timezone") { # /etc/timezone | |||
| 3615 | $in=new IO::File; | |||
| 3616 | $in->open("/etc/timezone","r"); | |||
| 3617 | while (! eof($in)) { | |||
| 3618 | $tmp=<$in>; | |||
| 3619 | next if ($tmp =~ /^\s*\043/); | |||
| 3620 | chomp($tmp); | |||
| 3621 | if ($tmp =~ /^\s*(.*?)\s*$/) { | |||
| 3622 | push(@tz,$1); | |||
| 3623 | last; | |||
| 3624 | } | |||
| 3625 | } | |||
| 3626 | $in->close; | |||
| 3627 | } | |||
| 3628 | ||||
| 3629 | # Now parse each one to find the first valid one. | |||
| 3630 | foreach $tz (@tz) { | |||
| 3631 | $tz =~ s/\s*$//; | |||
| 3632 | $tz =~ s/^\s*//; | |||
| 3633 | $tz =~ s/^://; | |||
| 3634 | next if ($tz eq ""); | |||
| 3635 | ||||
| 3636 | return uc($tz) | |||
| 3637 | if (defined $Zone{"n2o"}{lc($tz)}); | |||
| 3638 | ||||
| 3639 | if ($tz =~ /^[+-]\d{4}$/) { | |||
| 3640 | return $tz; | |||
| 3641 | } elsif ($tz =~ /^([+-]\d{2})(?::(\d{2}))?$/) { | |||
| 3642 | my($h,$m)=($1,$2); | |||
| 3643 | $m="00" if (! $m); | |||
| 3644 | return "$h$m"; | |||
| 3645 | } | |||
| 3646 | ||||
| 3647 | # Handle US/Eastern format | |||
| 3648 | if ($tz =~ /^$Zone{"tzones"}$/i) { | |||
| 3649 | $tmp=lc $1; | |||
| 3650 | $tz=$Zone{"tz2z"}{$tmp}; | |||
| 3651 | } | |||
| 3652 | ||||
| 3653 | # Handle STD#DST# format (and STD-#DST-# formats) | |||
| 3654 | if ($tz =~ /^([a-z]+)-?\d([a-z]+)-?\d?$/i) { | |||
| 3655 | ($std,$dst)=($1,$2); | |||
| 3656 | next if (! defined $Zone{"n2o"}{lc($std)} or | |||
| 3657 | ! defined $Zone{"n2o"}{lc($dst)}); | |||
| 3658 | $time = time(); | |||
| 3659 | ($null,$null,$null,$null,$null,$null,$null,$null,$isdst) = | |||
| 3660 | localtime($time); | |||
| 3661 | return uc($dst) if ($isdst); | |||
| 3662 | return uc($std); | |||
| 3663 | } | |||
| 3664 | } | |||
| 3665 | ||||
| 3666 | confess "ERROR: Date::Manip unable to determine Time Zone.\n"; | |||
| 3667 | } | |||
| 3668 | ||||
| 3669 | # Returns 1 if $date is a work day. If $time is non-zero, the time is | |||
| 3670 | # also checked to see if it falls within work hours. Returns "" if | |||
| 3671 | # an invalid date is passed in. | |||
| 3672 | sub Date_IsWorkDay { | |||
| 3673 | print "DEBUG: Date_IsWorkDay\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3674 | my($date,$time)=@_; | |||
| 3675 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3676 | $date=ParseDateString($date); | |||
| 3677 | return "" if (! $date); | |||
| 3678 | my($d)=$date; | |||
| 3679 | $d=Date_SetTime($date,$Cnf{"WorkDayBeg"}) if (! $time); | |||
| 3680 | ||||
| 3681 | my($y,$mon,$day,$h,$m,$s,$dow)=(); | |||
| 3682 | ($y,$mon,$day,$h,$m,$s)=_Date_Split($d, 1); | |||
| 3683 | $dow=Date_DayOfWeek($mon,$day,$y); | |||
| 3684 | ||||
| 3685 | return 0 if ($dow<$Cnf{"WorkWeekBeg"} or | |||
| 3686 | $dow>$Cnf{"WorkWeekEnd"} or | |||
| 3687 | "$h:$m" lt $Cnf{"WorkDayBeg"} or | |||
| 3688 | "$h:$m" ge $Cnf{"WorkDayEnd"}); | |||
| 3689 | ||||
| 3690 | if (! exists $Holiday{"dates"}{$y}) { | |||
| 3691 | # There will be recursion problems if we ever end up here twice. | |||
| 3692 | $Holiday{"dates"}{$y}={}; | |||
| 3693 | _Date_UpdateHolidays($y) | |||
| 3694 | } | |||
| 3695 | $d=Date_SetTime($date,"00:00:00"); | |||
| 3696 | return 0 if (exists $Holiday{"dates"}{$y}{$d}); | |||
| 3697 | 1; | |||
| 3698 | } | |||
| 3699 | ||||
| 3700 | # Finds the day $off work days from now. If $time is passed in, we must | |||
| 3701 | # also take into account the time of day. | |||
| 3702 | # | |||
| 3703 | # If $time is not passed in, day 0 is today (if today is a workday) or the | |||
| 3704 | # next work day if it isn't. In any case, the time of day is unaffected. | |||
| 3705 | # | |||
| 3706 | # If $time is passed in, day 0 is now (if now is part of a workday) or the | |||
| 3707 | # start of the very next work day. | |||
| 3708 | sub Date_NextWorkDay { | |||
| 3709 | print "DEBUG: Date_NextWorkDay\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3710 | my($date,$off,$time)=@_; | |||
| 3711 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3712 | $date=ParseDateString($date); | |||
| 3713 | my($err)=(); | |||
| 3714 | ||||
| 3715 | if (! Date_IsWorkDay($date,$time)) { | |||
| 3716 | if ($time) { | |||
| 3717 | while (1) { | |||
| 3718 | $date=Date_GetNext($date,undef,0,$Cnf{"WorkDayBeg"}); | |||
| 3719 | last if (Date_IsWorkDay($date,$time)); | |||
| 3720 | } | |||
| 3721 | } else { | |||
| 3722 | while (1) { | |||
| 3723 | $date=_DateCalc_DateDelta($date,"+0:0:0:1:0:0:0",\$err,0); | |||
| 3724 | last if (Date_IsWorkDay($date,$time)); | |||
| 3725 | } | |||
| 3726 | } | |||
| 3727 | } | |||
| 3728 | ||||
| 3729 | while ($off>0) { | |||
| 3730 | while (1) { | |||
| 3731 | $date=_DateCalc_DateDelta($date,"+0:0:0:1:0:0:0",\$err,0); | |||
| 3732 | last if (Date_IsWorkDay($date,$time)); | |||
| 3733 | } | |||
| 3734 | $off--; | |||
| 3735 | } | |||
| 3736 | ||||
| 3737 | return $date; | |||
| 3738 | } | |||
| 3739 | ||||
| 3740 | # Finds the day $off work days before now. If $time is passed in, we must | |||
| 3741 | # also take into account the time of day. | |||
| 3742 | # | |||
| 3743 | # If $time is not passed in, day 0 is today (if today is a workday) or the | |||
| 3744 | # previous work day if it isn't. In any case, the time of day is unaffected. | |||
| 3745 | # | |||
| 3746 | # If $time is passed in, day 0 is now (if now is part of a workday) or the | |||
| 3747 | # end of the previous work period. Note that since the end of a work day | |||
| 3748 | # will automatically be turned into the start of the next one, this time | |||
| 3749 | # may actually be treated as AFTER the current time. | |||
| 3750 | sub Date_PrevWorkDay { | |||
| 3751 | print "DEBUG: Date_PrevWorkDay\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3752 | my($date,$off,$time)=@_; | |||
| 3753 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3754 | $date=ParseDateString($date); | |||
| 3755 | my($err)=(); | |||
| 3756 | ||||
| 3757 | if (! Date_IsWorkDay($date,$time)) { | |||
| 3758 | if ($time) { | |||
| 3759 | while (1) { | |||
| 3760 | $date=Date_GetPrev($date,undef,0,$Cnf{"WorkDayEnd"}); | |||
| 3761 | last if (Date_IsWorkDay($date,$time)); | |||
| 3762 | } | |||
| 3763 | while (1) { | |||
| 3764 | $date=Date_GetNext($date,undef,0,$Cnf{"WorkDayBeg"}); | |||
| 3765 | last if (Date_IsWorkDay($date,$time)); | |||
| 3766 | } | |||
| 3767 | } else { | |||
| 3768 | while (1) { | |||
| 3769 | $date=_DateCalc_DateDelta($date,"-0:0:0:1:0:0:0",\$err,0); | |||
| 3770 | last if (Date_IsWorkDay($date,$time)); | |||
| 3771 | } | |||
| 3772 | } | |||
| 3773 | } | |||
| 3774 | ||||
| 3775 | while ($off>0) { | |||
| 3776 | while (1) { | |||
| 3777 | $date=_DateCalc_DateDelta($date,"-0:0:0:1:0:0:0",\$err,0); | |||
| 3778 | last if (Date_IsWorkDay($date,$time)); | |||
| 3779 | } | |||
| 3780 | $off--; | |||
| 3781 | } | |||
| 3782 | ||||
| 3783 | return $date; | |||
| 3784 | } | |||
| 3785 | ||||
| 3786 | # This finds the nearest workday to $date. If $date is a workday, it | |||
| 3787 | # is returned. | |||
| 3788 | sub Date_NearestWorkDay { | |||
| 3789 | print "DEBUG: Date_NearestWorkDay\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3790 | my($date,$tomorrow)=@_; | |||
| 3791 | Date_Init() if (! $Curr{"InitDone"}); | |||
| 3792 | $date=ParseDateString($date); | |||
| 3793 | my($a,$b,$dela,$delb,$err)=(); | |||
| 3794 | $tomorrow=$Cnf{"TomorrowFirst"} if (! defined $tomorrow); | |||
| 3795 | ||||
| 3796 | return $date if (Date_IsWorkDay($date)); | |||
| 3797 | ||||
| 3798 | # Find the nearest one. | |||
| 3799 | if ($tomorrow) { | |||
| 3800 | $dela="+0:0:0:1:0:0:0"; | |||
| 3801 | $delb="-0:0:0:1:0:0:0"; | |||
| 3802 | } else { | |||
| 3803 | $dela="-0:0:0:1:0:0:0"; | |||
| 3804 | $delb="+0:0:0:1:0:0:0"; | |||
| 3805 | } | |||
| 3806 | $a=$b=$date; | |||
| 3807 | ||||
| 3808 | while (1) { | |||
| 3809 | $a=_DateCalc_DateDelta($a,$dela,\$err); | |||
| 3810 | return $a if (Date_IsWorkDay($a)); | |||
| 3811 | $b=_DateCalc_DateDelta($b,$delb,\$err); | |||
| 3812 | return $b if (Date_IsWorkDay($b)); | |||
| 3813 | } | |||
| 3814 | } | |||
| 3815 | ||||
| 3816 | # Date_NthDayOfYear($y,$n); | |||
| 3817 | # Returns a list of (YYYY,MM,DD,HH,MM,SS) for the Nth day of the year. | |||
| 3818 | sub Date_NthDayOfYear { | |||
| 3819 | 3 | 2.16ms | 719µs | no integer; # spent 10µs making 1 call to integer::unimport |
| 3820 | print "DEBUG: Date_NthDayOfYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3821 | my($y,$n)=@_; | |||
| 3822 | $y=$Curr{"Y"} if (! $y); | |||
| 3823 | $n=1 if (! defined $n or $n eq ""); | |||
| 3824 | $n+=0; # to turn 023 into 23 | |||
| 3825 | $y=_Date_FixYear($y) if (length($y)<4); | |||
| 3826 | my $leap=Date_LeapYear($y); | |||
| 3827 | return () if ($n<1); | |||
| 3828 | return () if ($n >= ($leap ? 367 : 366)); | |||
| 3829 | ||||
| 3830 | my(@d_in_m)=(31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 3831 | $d_in_m[1]=29 if ($leap); | |||
| 3832 | ||||
| 3833 | # Calculate the hours, minutes, and seconds into the day. | |||
| 3834 | my $remain=($n - int($n))*24; | |||
| 3835 | my $h=int($remain); | |||
| 3836 | $remain=($remain - $h)*60; | |||
| 3837 | my $mn=int($remain); | |||
| 3838 | $remain=($remain - $mn)*60; | |||
| 3839 | my $s=$remain; | |||
| 3840 | ||||
| 3841 | # Calculate the month and the day. | |||
| 3842 | my($m,$d)=(0,0); | |||
| 3843 | $n=int($n); | |||
| 3844 | while ($n>0) { | |||
| 3845 | $m++; | |||
| 3846 | if ($n<=$d_in_m[0]) { | |||
| 3847 | $d=int($n); | |||
| 3848 | $n=0; | |||
| 3849 | } else { | |||
| 3850 | $n-= $d_in_m[0]; | |||
| 3851 | shift(@d_in_m); | |||
| 3852 | } | |||
| 3853 | } | |||
| 3854 | ||||
| 3855 | ($y,$m,$d,$h,$mn,$s); | |||
| 3856 | } | |||
| 3857 | ||||
| 3858 | ######################################################################## | |||
| 3859 | # NOT FOR EXPORT | |||
| 3860 | ######################################################################## | |||
| 3861 | ||||
| 3862 | # This is used in Date_Init to fill in a hash based on international | |||
| 3863 | # data. It takes a list of keys and values and returns both a hash | |||
| 3864 | # with these values and a regular expression of keys. | |||
| 3865 | # | |||
| 3866 | # IN: | |||
| 3867 | # $data = [ key1 val1 key2 val2 ... ] | |||
| 3868 | # $opts = lc : lowercase the keys in the regexp | |||
| 3869 | # sort : sort (by length) the keys in the regexp | |||
| 3870 | # back : create a regexp with a back reference | |||
| 3871 | # escape : escape all strings in the regexp | |||
| 3872 | # | |||
| 3873 | # OUT: | |||
| 3874 | # $regexp = '(?:key1|key2|...)' | |||
| 3875 | # $hash = { key1=>val1 key2=>val2 ... } | |||
| 3876 | ||||
| 3877 | sub _Date_InitHash { | |||
| 3878 | print "DEBUG: _Date_InitHash\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3879 | my($data,$regexp,$opts,$hash)=@_; | |||
| 3880 | my(@data)=@$data; | |||
| 3881 | my($key,$val,@list)=(); | |||
| 3882 | ||||
| 3883 | # Parse the options | |||
| 3884 | my($lc,$sort,$back,$escape)=(0,0,0,0); | |||
| 3885 | $lc=1 if ($opts =~ /lc/i); | |||
| 3886 | $sort=1 if ($opts =~ /sort/i); | |||
| 3887 | $back=1 if ($opts =~ /back/i); | |||
| 3888 | $escape=1 if ($opts =~ /escape/i); | |||
| 3889 | ||||
| 3890 | # Create the hash | |||
| 3891 | while (@data) { | |||
| 3892 | ($key,$val,@data)=@data; | |||
| 3893 | $key=lc($key) if ($lc); | |||
| 3894 | $$hash{$key}=$val; | |||
| 3895 | } | |||
| 3896 | ||||
| 3897 | # Create the regular expression | |||
| 3898 | if ($regexp) { | |||
| 3899 | @list=keys(%$hash); | |||
| 3900 | @list=sort _sortByLength(@list) if ($sort); | |||
| 3901 | if ($escape) { | |||
| 3902 | foreach $val (@list) { | |||
| 3903 | $val="\Q$val\E"; | |||
| 3904 | } | |||
| 3905 | } | |||
| 3906 | if ($back) { | |||
| 3907 | $$regexp="(" . join("|",@list) . ")"; | |||
| 3908 | } else { | |||
| 3909 | $$regexp="(?:" . join("|",@list) . ")"; | |||
| 3910 | } | |||
| 3911 | } | |||
| 3912 | } | |||
| 3913 | ||||
| 3914 | # This is used in Date_Init to fill in regular expressions, lists, and | |||
| 3915 | # hashes based on international data. It takes a list of lists which have | |||
| 3916 | # to be stored as regular expressions (to find any element in the list), | |||
| 3917 | # lists, and hashes (indicating the location in the lists). | |||
| 3918 | # | |||
| 3919 | # IN: | |||
| 3920 | # $data = [ [ [ valA1 valA2 ... ][ valA1' valA2' ... ] ... ] | |||
| 3921 | # [ [ valB1 valB2 ... ][ valB1' valB2' ... ] ... ] | |||
| 3922 | # ... | |||
| 3923 | # [ [ valZ1 valZ2 ... ] [valZ1' valZ1' ... ] ... ] ] | |||
| 3924 | # $lists = [ \@listA \@listB ... \@listZ ] | |||
| 3925 | # $opts = lc : lowercase the values in the regexp | |||
| 3926 | # sort : sort (by length) the values in the regexp | |||
| 3927 | # back : create a regexp with a back reference | |||
| 3928 | # escape : escape all strings in the regexp | |||
| 3929 | # $hash = [ \%hash, TYPE ] | |||
| 3930 | # TYPE 0 : $hash{ valBn=>n-1 } | |||
| 3931 | # TYPE 1 : $hash{ valBn=>n } | |||
| 3932 | # | |||
| 3933 | # OUT: | |||
| 3934 | # $regexp = '(?:valA1|valA2|...|valB1|...)' | |||
| 3935 | # $lists = [ [ valA1 valA2 ... ] # only the 1st list (or | |||
| 3936 | # [ valB1 valB2 ... ] ... ] # 2nd for int. characters) | |||
| 3937 | # $hash | |||
| 3938 | ||||
| 3939 | sub _Date_InitLists { | |||
| 3940 | print "DEBUG: _Date_InitLists\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 3941 | my($data,$regexp,$opts,$lists,$hash)=@_; | |||
| 3942 | my(@data)=@$data; | |||
| 3943 | my(@lists)=@$lists; | |||
| 3944 | my($i,@ele,$ele,@list,$j,$tmp)=(); | |||
| 3945 | ||||
| 3946 | # Parse the options | |||
| 3947 | my($lc,$sort,$back,$escape)=(0,0,0,0); | |||
| 3948 | $lc=1 if ($opts =~ /lc/i); | |||
| 3949 | $sort=1 if ($opts =~ /sort/i); | |||
| 3950 | $back=1 if ($opts =~ /back/i); | |||
| 3951 | $escape=1 if ($opts =~ /escape/i); | |||
| 3952 | ||||
| 3953 | # Set each of the lists | |||
| 3954 | if (@lists) { | |||
| 3955 | confess "ERROR: _Date_InitLists: lists must be 1 per data\n" | |||
| 3956 | if ($#lists != $#data); | |||
| 3957 | for ($i=0; $i<=$#data; $i++) { | |||
| 3958 | @ele=@{ $data[$i] }; | |||
| 3959 | if ($Cnf{"IntCharSet"} && $#ele>0) { | |||
| 3960 | @{ $lists[$i] } = @{ $ele[1] }; | |||
| 3961 | } else { | |||
| 3962 | @{ $lists[$i] } = @{ $ele[0] }; | |||
| 3963 | } | |||
| 3964 | } | |||
| 3965 | } | |||
| 3966 | ||||
| 3967 | # Create the hash | |||
| 3968 | my($hashtype,$hashsave,%hash)=(); | |||
| 3969 | if (@$hash) { | |||
| 3970 | ($hash,$hashtype)=@$hash; | |||
| 3971 | $hashsave=1; | |||
| 3972 | } else { | |||
| 3973 | $hashtype=0; | |||
| 3974 | $hashsave=0; | |||
| 3975 | } | |||
| 3976 | for ($i=0; $i<=$#data; $i++) { | |||
| 3977 | @ele=@{ $data[$i] }; | |||
| 3978 | foreach $ele (@ele) { | |||
| 3979 | @list = @{ $ele }; | |||
| 3980 | for ($j=0; $j<=$#list; $j++) { | |||
| 3981 | $tmp=$list[$j]; | |||
| 3982 | next if (! $tmp); | |||
| 3983 | $tmp=lc($tmp) if ($lc); | |||
| 3984 | $hash{$tmp}= $j+$hashtype; | |||
| 3985 | } | |||
| 3986 | } | |||
| 3987 | } | |||
| 3988 | %$hash = %hash if ($hashsave); | |||
| 3989 | ||||
| 3990 | # Create the regular expression | |||
| 3991 | if ($regexp) { | |||
| 3992 | @list=keys(%hash); | |||
| 3993 | @list=sort _sortByLength(@list) if ($sort); | |||
| 3994 | if ($escape) { | |||
| 3995 | foreach $ele (@list) { | |||
| 3996 | $ele="\Q$ele\E"; | |||
| 3997 | } | |||
| 3998 | } | |||
| 3999 | if ($back) { | |||
| 4000 | $$regexp="(" . join("|",@list) . ")"; | |||
| 4001 | } else { | |||
| 4002 | $$regexp="(?:" . join("|",@list) . ")"; | |||
| 4003 | } | |||
| 4004 | } | |||
| 4005 | } | |||
| 4006 | ||||
| 4007 | # This is used in Date_Init to fill in regular expressions and lists based | |||
| 4008 | # on international data. This takes a list of strings and returns a regular | |||
| 4009 | # expression (to find any one of them). | |||
| 4010 | # | |||
| 4011 | # IN: | |||
| 4012 | # $data = [ string1 string2 ... ] | |||
| 4013 | # $opts = lc : lowercase the values in the regexp | |||
| 4014 | # sort : sort (by length) the values in the regexp | |||
| 4015 | # back : create a regexp with a back reference | |||
| 4016 | # escape : escape all strings in the regexp | |||
| 4017 | # | |||
| 4018 | # OUT: | |||
| 4019 | # $regexp = '(string1|string2|...)' | |||
| 4020 | ||||
| 4021 | sub _Date_InitStrings { | |||
| 4022 | print "DEBUG: _Date_InitStrings\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4023 | my($data,$regexp,$opts)=@_; | |||
| 4024 | my(@list)=@{ $data }; | |||
| 4025 | ||||
| 4026 | # Parse the options | |||
| 4027 | my($lc,$sort,$back,$escape)=(0,0,0,0); | |||
| 4028 | $lc=1 if ($opts =~ /lc/i); | |||
| 4029 | $sort=1 if ($opts =~ /sort/i); | |||
| 4030 | $back=1 if ($opts =~ /back/i); | |||
| 4031 | $escape=1 if ($opts =~ /escape/i); | |||
| 4032 | ||||
| 4033 | # Create the regular expression | |||
| 4034 | my($ele)=(); | |||
| 4035 | @list=sort _sortByLength(@list) if ($sort); | |||
| 4036 | if ($escape) { | |||
| 4037 | foreach $ele (@list) { | |||
| 4038 | $ele="\Q$ele\E"; | |||
| 4039 | } | |||
| 4040 | } | |||
| 4041 | if ($back) { | |||
| 4042 | $$regexp="(" . join("|",@list) . ")"; | |||
| 4043 | } else { | |||
| 4044 | $$regexp="(?:" . join("|",@list) . ")"; | |||
| 4045 | } | |||
| 4046 | $$regexp=lc($$regexp) if ($lc); | |||
| 4047 | } | |||
| 4048 | ||||
| 4049 | # items is passed in (either as a space separated string, or a reference to | |||
| 4050 | # a list) and a regular expression which matches any one of the items is | |||
| 4051 | # prepared. The regular expression will be of one of the forms: | |||
| 4052 | # "(a|b)" @list not empty, back option included | |||
| 4053 | # "(?:a|b)" @list not empty | |||
| 4054 | # "()" @list empty, back option included | |||
| 4055 | # "" @list empty | |||
| 4056 | # $options is a string which contains any of the following strings: | |||
| 4057 | # back : the regular expression has a backreference | |||
| 4058 | # opt : the regular expression is optional and a "?" is appended in | |||
| 4059 | # the first two forms | |||
| 4060 | # optws : the regular expression is optional and may be replaced by | |||
| 4061 | # whitespace | |||
| 4062 | # optWs : the regular expression is optional, but if not present, must | |||
| 4063 | # be replaced by whitespace | |||
| 4064 | # sort : the items in the list are sorted by length (longest first) | |||
| 4065 | # lc : the string is lowercased | |||
| 4066 | # under : any underscores are converted to spaces | |||
| 4067 | # pre : it may be preceded by whitespace | |||
| 4068 | # Pre : it must be preceded by whitespace | |||
| 4069 | # PRE : it must be preceded by whitespace or the start | |||
| 4070 | # post : it may be followed by whitespace | |||
| 4071 | # Post : it must be followed by whitespace | |||
| 4072 | # POST : it must be followed by whitespace or the end | |||
| 4073 | # Spaces due to pre/post options will not be included in the back reference. | |||
| 4074 | # | |||
| 4075 | # If $array is included, then the elements will also be returned as a list. | |||
| 4076 | # $array is a string which may contain any of the following: | |||
| 4077 | # keys : treat the list as a hash and only the keys go into the regexp | |||
| 4078 | # key0 : treat the list as the values of a hash with keys 0 .. N-1 | |||
| 4079 | # key1 : treat the list as the values of a hash with keys 1 .. N | |||
| 4080 | # val0 : treat the list as the keys of a hash with values 0 .. N-1 | |||
| 4081 | # val1 : treat the list as the keys of a hash with values 1 .. N | |||
| 4082 | ||||
| 4083 | # _Date_InitLists([$lang{"month_name"},$lang{"month_abb"}], | |||
| 4084 | # [\$Month,"lc,sort,back"], | |||
| 4085 | # [\@Month,\@Mon], | |||
| 4086 | # [\%Month,1]); | |||
| 4087 | ||||
| 4088 | # This is used in Date_Init to prepare regular expressions. A list of | |||
| 4089 | # items is passed in (either as a space separated string, or a reference to | |||
| 4090 | # a list) and a regular expression which matches any one of the items is | |||
| 4091 | # prepared. The regular expression will be of one of the forms: | |||
| 4092 | # "(a|b)" @list not empty, back option included | |||
| 4093 | # "(?:a|b)" @list not empty | |||
| 4094 | # "()" @list empty, back option included | |||
| 4095 | # "" @list empty | |||
| 4096 | # $options is a string which contains any of the following strings: | |||
| 4097 | # back : the regular expression has a backreference | |||
| 4098 | # opt : the regular expression is optional and a "?" is appended in | |||
| 4099 | # the first two forms | |||
| 4100 | # optws : the regular expression is optional and may be replaced by | |||
| 4101 | # whitespace | |||
| 4102 | # optWs : the regular expression is optional, but if not present, must | |||
| 4103 | # be replaced by whitespace | |||
| 4104 | # sort : the items in the list are sorted by length (longest first) | |||
| 4105 | # lc : the string is lowercased | |||
| 4106 | # under : any underscores are converted to spaces | |||
| 4107 | # pre : it may be preceded by whitespace | |||
| 4108 | # Pre : it must be preceded by whitespace | |||
| 4109 | # PRE : it must be preceded by whitespace or the start | |||
| 4110 | # post : it may be followed by whitespace | |||
| 4111 | # Post : it must be followed by whitespace | |||
| 4112 | # POST : it must be followed by whitespace or the end | |||
| 4113 | # Spaces due to pre/post options will not be included in the back reference. | |||
| 4114 | # | |||
| 4115 | # If $array is included, then the elements will also be returned as a list. | |||
| 4116 | # $array is a string which may contain any of the following: | |||
| 4117 | # keys : treat the list as a hash and only the keys go into the regexp | |||
| 4118 | # key0 : treat the list as the values of a hash with keys 0 .. N-1 | |||
| 4119 | # key1 : treat the list as the values of a hash with keys 1 .. N | |||
| 4120 | # val0 : treat the list as the keys of a hash with values 0 .. N-1 | |||
| 4121 | # val1 : treat the list as the keys of a hash with values 1 .. N | |||
| 4122 | sub _Date_Regexp { | |||
| 4123 | print "DEBUG: _Date_Regexp\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4124 | my($list,$options,$array)=@_; | |||
| 4125 | my(@list,$ret,%hash,$i)=(); | |||
| 4126 | local($_)=(); | |||
| 4127 | $options="" if (! defined $options); | |||
| 4128 | $array="" if (! defined $array); | |||
| 4129 | ||||
| 4130 | my($sort,$lc,$under)=(0,0,0); | |||
| 4131 | $sort =1 if ($options =~ /sort/i); | |||
| 4132 | $lc =1 if ($options =~ /lc/i); | |||
| 4133 | $under=1 if ($options =~ /under/i); | |||
| 4134 | my($back,$opt,$pre,$post,$ws)=("?:","","","",""); | |||
| 4135 | $back ="" if ($options =~ /back/i); | |||
| 4136 | $opt ="?" if ($options =~ /opt/i); | |||
| 4137 | $pre ='\s*' if ($options =~ /pre/); | |||
| 4138 | $pre ='\s+' if ($options =~ /Pre/); | |||
| 4139 | $pre ='(?:\s+|^)' if ($options =~ /PRE/); | |||
| 4140 | $post ='\s*' if ($options =~ /post/); | |||
| 4141 | $post ='\s+' if ($options =~ /Post/); | |||
| 4142 | $post ='(?:$|\s+)' if ($options =~ /POST/); | |||
| 4143 | $ws ='\s*' if ($options =~ /optws/); | |||
| 4144 | $ws ='\s+' if ($options =~ /optws/); | |||
| 4145 | ||||
| 4146 | my($hash,$keys,$key0,$key1,$val0,$val1)=(0,0,0,0,0,0); | |||
| 4147 | $keys =1 if ($array =~ /keys/i); | |||
| 4148 | $key0 =1 if ($array =~ /key0/i); | |||
| 4149 | $key1 =1 if ($array =~ /key1/i); | |||
| 4150 | $val0 =1 if ($array =~ /val0/i); | |||
| 4151 | $val1 =1 if ($array =~ /val1/i); | |||
| 4152 | $hash =1 if ($keys or $key0 or $key1 or $val0 or $val1); | |||
| 4153 | ||||
| 4154 | my($ref)=ref $list; | |||
| 4155 | if (! $ref) { | |||
| 4156 | $list =~ s/\s*$//; | |||
| 4157 | $list =~ s/^\s*//; | |||
| 4158 | $list =~ s/\s+/&&&/g; | |||
| 4159 | } elsif ($ref eq "ARRAY") { | |||
| 4160 | $list = join("&&&",@$list); | |||
| 4161 | } else { | |||
| 4162 | confess "ERROR: _Date_Regexp.\n"; | |||
| 4163 | } | |||
| 4164 | ||||
| 4165 | if (! $list) { | |||
| 4166 | if ($back eq "") { | |||
| 4167 | return "()"; | |||
| 4168 | } else { | |||
| 4169 | return ""; | |||
| 4170 | } | |||
| 4171 | } | |||
| 4172 | ||||
| 4173 | $list=lc($list) if ($lc); | |||
| 4174 | $list=~ s/_/ /g if ($under); | |||
| 4175 | @list=split(/&&&/,$list); | |||
| 4176 | if ($keys) { | |||
| 4177 | %hash=@list; | |||
| 4178 | @list=keys %hash; | |||
| 4179 | } elsif ($key0 or $key1 or $val0 or $val1) { | |||
| 4180 | $i=0; | |||
| 4181 | $i=1 if ($key1 or $val1); | |||
| 4182 | if ($key0 or $key1) { | |||
| 4183 | %hash= map { $_,$i++ } @list; | |||
| 4184 | } else { | |||
| 4185 | %hash= map { $i++,$_ } @list; | |||
| 4186 | } | |||
| 4187 | } | |||
| 4188 | @list=sort _sortByLength(@list) if ($sort); | |||
| 4189 | ||||
| 4190 | $ret="($back" . join("|",@list) . ")"; | |||
| 4191 | $ret="(?:$pre$ret$post)" if ($pre or $post); | |||
| 4192 | $ret.=$opt; | |||
| 4193 | $ret="(?:$ret|$ws)" if ($ws); | |||
| 4194 | ||||
| 4195 | if ($array and $hash) { | |||
| 4196 | return ($ret,%hash); | |||
| 4197 | } elsif ($array) { | |||
| 4198 | return ($ret,@list); | |||
| 4199 | } else { | |||
| 4200 | return $ret; | |||
| 4201 | } | |||
| 4202 | } | |||
| 4203 | ||||
| 4204 | # This will produce a delta with the correct number of signs. At most two | |||
| 4205 | # signs will be in it normally (one before the year, and one in front of | |||
| 4206 | # the day), but if appropriate, signs will be in front of all elements. | |||
| 4207 | # Also, as many of the signs will be equivalent as possible. | |||
| 4208 | sub _Delta_Normalize { | |||
| 4209 | print "DEBUG: _Delta_Normalize\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4210 | my($delta,$mode)=@_; | |||
| 4211 | return "" if (! $delta); | |||
| 4212 | return "+0:+0:+0:+0:+0:+0:+0" | |||
| 4213 | if ($delta =~ /^([+-]?0+:){6}[+-]?0+$/ and $Cnf{"DeltaSigns"}); | |||
| 4214 | return "+0:0:0:0:0:0:0" if ($delta =~ /^([+-]?0+:){6}[+-]?0+$/); | |||
| 4215 | ||||
| 4216 | my($tmp,$sign1,$sign2,$len)=(); | |||
| 4217 | ||||
| 4218 | # Calculate the length of the day in minutes | |||
| 4219 | $len=24*60; | |||
| 4220 | $len=$Curr{"WDlen"} if ($mode==2 || $mode==3); | |||
| 4221 | ||||
| 4222 | # We have to get the sign of every component explicitely so that a "-0" | |||
| 4223 | # or "+0" doesn't get lost by treating it numerically (i.e. "-0:0:2" must | |||
| 4224 | # be a negative delta). | |||
| 4225 | ||||
| 4226 | my($y,$mon,$w,$d,$h,$m,$s)=_Delta_Split($delta); | |||
| 4227 | ||||
| 4228 | # We need to make sure that the signs of all parts of a delta are the | |||
| 4229 | # same. The easiest way to do this is to convert all of the large | |||
| 4230 | # components to the smallest ones, then convert the smaller components | |||
| 4231 | # back to the larger ones. | |||
| 4232 | ||||
| 4233 | # Do the year/month part | |||
| 4234 | ||||
| 4235 | $mon += $y*12; # convert y to m | |||
| 4236 | $sign1="+"; | |||
| 4237 | if ($mon<0) { | |||
| 4238 | $mon *= -1; | |||
| 4239 | $sign1="-"; | |||
| 4240 | } | |||
| 4241 | ||||
| 4242 | $y = $mon/12; # convert m to y | |||
| 4243 | $mon -= $y*12; | |||
| 4244 | ||||
| 4245 | $y=0 if ($y eq "-0"); # get around silly -0 problem | |||
| 4246 | $mon=0 if ($mon eq "-0"); | |||
| 4247 | ||||
| 4248 | # Do the wk/day/hour/min/sec part | |||
| 4249 | ||||
| 4250 | { | |||
| 4251 | # Unfortunately, $s is overflowing for dates more than ~70 years | |||
| 4252 | # apart. | |||
| 4253 | 3 | 19.8ms | 6.61ms | no integer; # spent 13µs making 1 call to integer::unimport |
| 4254 | ||||
| 4255 | if ($mode==3 || $mode==2) { | |||
| 4256 | $s += $d*$len*60 + $h*3600 + $m*60; # convert d/h/m to s | |||
| 4257 | } else { | |||
| 4258 | $s += ($d+7*$w)*$len*60 + $h*3600 + $m*60; # convert w/d/h/m to s | |||
| 4259 | } | |||
| 4260 | $sign2="+"; | |||
| 4261 | if ($s<0) { | |||
| 4262 | $s*=-1; | |||
| 4263 | $sign2="-"; | |||
| 4264 | } | |||
| 4265 | ||||
| 4266 | $m = int($s/60); # convert s to m | |||
| 4267 | $s -= $m*60; | |||
| 4268 | $d = int($m/$len); # convert m to d | |||
| 4269 | $m -= $d*$len; | |||
| 4270 | ||||
| 4271 | # The rest should be fine. | |||
| 4272 | } | |||
| 4273 | $h = $m/60; # convert m to h | |||
| 4274 | $m -= $h*60; | |||
| 4275 | if ($mode == 3 || $mode == 2) { | |||
| 4276 | $w = $w*1; # get around +0 problem | |||
| 4277 | } else { | |||
| 4278 | $w = $d/7; # convert d to w | |||
| 4279 | $d -= $w*7; | |||
| 4280 | } | |||
| 4281 | ||||
| 4282 | $w=0 if ($w eq "-0"); # get around silly -0 problem | |||
| 4283 | $d=0 if ($d eq "-0"); | |||
| 4284 | $h=0 if ($h eq "-0"); | |||
| 4285 | $m=0 if ($m eq "-0"); | |||
| 4286 | $s=0 if ($s eq "-0"); | |||
| 4287 | ||||
| 4288 | # Only include two signs if necessary | |||
| 4289 | $sign1=$sign2 if ($y==0 and $mon==0); | |||
| 4290 | $sign2=$sign1 if ($w==0 and $d==0 and $h==0 and $m==0 and $s==0); | |||
| 4291 | $sign2="" if ($sign1 eq $sign2 and ! $Cnf{"DeltaSigns"}); | |||
| 4292 | ||||
| 4293 | if ($Cnf{"DeltaSigns"}) { | |||
| 4294 | return "$sign1$y:$sign1$mon:$sign2$w:$sign2$d:$sign2$h:$sign2$m:$sign2$s"; | |||
| 4295 | } else { | |||
| 4296 | return "$sign1$y:$mon:$sign2$w:$d:$h:$m:$s"; | |||
| 4297 | } | |||
| 4298 | } | |||
| 4299 | ||||
| 4300 | # This checks a delta to make sure it is valid. If it is, it splits | |||
| 4301 | # it and returns the elements with a sign on each. The 2nd argument | |||
| 4302 | # specifies the default sign. Blank elements are set to 0. If the | |||
| 4303 | # third element is non-nil, exactly 7 elements must be included. | |||
| 4304 | sub _Delta_Split { | |||
| 4305 | print "DEBUG: _Delta_Split\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4306 | my($delta,$sign,$exact)=@_; | |||
| 4307 | my(@delta)=split(/:/,$delta); | |||
| 4308 | return () if ($exact and $#delta != 6); | |||
| 4309 | my($i)=(); | |||
| 4310 | $sign="+" if (! defined $sign); | |||
| 4311 | for ($i=0; $i<=$#delta; $i++) { | |||
| 4312 | $delta[$i]="0" if (! $delta[$i]); | |||
| 4313 | return () if ($delta[$i] !~ /^[+-]?\d+$/); | |||
| 4314 | $sign = ($delta[$i] =~ s/^([+-])// ? $1 : $sign); | |||
| 4315 | $delta[$i] = $sign.$delta[$i]; | |||
| 4316 | } | |||
| 4317 | @delta; | |||
| 4318 | } | |||
| 4319 | ||||
| 4320 | # Reads up to 3 arguments. $h may contain the time in any international | |||
| 4321 | # format. Any empty elements are set to 0. | |||
| 4322 | sub _Date_ParseTime { | |||
| 4323 | print "DEBUG: _Date_ParseTime\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4324 | my($h,$m,$s)=@_; | |||
| 4325 | my($t)=_CheckTime("one"); | |||
| 4326 | ||||
| 4327 | if (defined $h and $h =~ /$t/) { | |||
| 4328 | $h=$1; | |||
| 4329 | $m=$2; | |||
| 4330 | $s=$3 if (defined $3); | |||
| 4331 | } | |||
| 4332 | $h="00" if (! defined $h); | |||
| 4333 | $m="00" if (! defined $m); | |||
| 4334 | $s="00" if (! defined $s); | |||
| 4335 | ||||
| 4336 | ($h,$m,$s); | |||
| 4337 | } | |||
| 4338 | ||||
| 4339 | # Forms a date with the 6 elements passed in (all of which must be defined). | |||
| 4340 | # No check as to validity is made. | |||
| 4341 | sub _Date_Join { | |||
| 4342 | print "DEBUG: _Date_Join\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4343 | foreach (0 .. $#_) { | |||
| 4344 | croak "undefined arg $_ to _Date_Join()" if not defined $_[$_]; | |||
| 4345 | } | |||
| 4346 | my($y,$m,$d,$h,$mn,$s)=@_; | |||
| 4347 | my($ym,$md,$dh,$hmn,$mns)=(); | |||
| 4348 | ||||
| 4349 | if ($Cnf{"Internal"} == 0) { | |||
| 4350 | $ym=$md=$dh=""; | |||
| 4351 | $hmn=$mns=":"; | |||
| 4352 | ||||
| 4353 | } elsif ($Cnf{"Internal"} == 1) { | |||
| 4354 | $ym=$md=$dh=$hmn=$mns=""; | |||
| 4355 | ||||
| 4356 | } elsif ($Cnf{"Internal"} == 2) { | |||
| 4357 | $ym=$md="-"; | |||
| 4358 | $dh=" "; | |||
| 4359 | $hmn=$mns=":"; | |||
| 4360 | ||||
| 4361 | } else { | |||
| 4362 | confess "ERROR: Invalid internal format in _Date_Join.\n"; | |||
| 4363 | } | |||
| 4364 | $m="0$m" if (length($m)==1); | |||
| 4365 | $d="0$d" if (length($d)==1); | |||
| 4366 | $h="0$h" if (length($h)==1); | |||
| 4367 | $mn="0$mn" if (length($mn)==1); | |||
| 4368 | $s="0$s" if (length($s)==1); | |||
| 4369 | "$y$ym$m$md$d$dh$h$hmn$mn$mns$s"; | |||
| 4370 | } | |||
| 4371 | ||||
| 4372 | # This checks a time. If it is valid, it splits it and returns 3 elements. | |||
| 4373 | # If "one" or "two" is passed in, a regexp with 1/2 or 2 digit hours is | |||
| 4374 | # returned. | |||
| 4375 | sub _CheckTime { | |||
| 4376 | print "DEBUG: _CheckTime\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4377 | my($time)=@_; | |||
| 4378 | my($h)='(?:0?[0-9]|1[0-9]|2[0-3])'; | |||
| 4379 | my($h2)='(?:0[0-9]|1[0-9]|2[0-3])'; | |||
| 4380 | my($m)='[0-5][0-9]'; | |||
| 4381 | my($s)=$m; | |||
| 4382 | my($hm)="(?:". $Lang{$Cnf{"Language"}}{"SepHM"} ."|:)"; | |||
| 4383 | my($ms)="(?:". $Lang{$Cnf{"Language"}}{"SepMS"} ."|:)"; | |||
| 4384 | my($ss)=$Lang{$Cnf{"Language"}}{"SepSS"}; | |||
| 4385 | my($t)="^($h)$hm($m)(?:$ms($s)(?:$ss\\d+)?)?\$"; | |||
| 4386 | if ($time eq "one") { | |||
| 4387 | return $t; | |||
| 4388 | } elsif ($time eq "two") { | |||
| 4389 | $t="^($h2)$hm($m)(?:$ms($s)(?:$ss\\d+)?)?\$"; | |||
| 4390 | return $t; | |||
| 4391 | } | |||
| 4392 | ||||
| 4393 | if ($time =~ /$t/i) { | |||
| 4394 | ($h,$m,$s)=($1,$2,$3); | |||
| 4395 | $h="0$h" if (length($h)<2); | |||
| 4396 | $m="0$m" if (length($m)<2); | |||
| 4397 | $s="00" if (! defined $s); | |||
| 4398 | return ($h,$m,$s); | |||
| 4399 | } else { | |||
| 4400 | return (); | |||
| 4401 | } | |||
| 4402 | } | |||
| 4403 | ||||
| 4404 | # This checks a recurrence. If it is valid, it splits it and returns the | |||
| 4405 | # elements. Otherwise, it returns an empty list. | |||
| 4406 | # ($recur0,$recur1,$flags,$dateb,$date0,$date1)=_Recur_Split($recur); | |||
| 4407 | sub _Recur_Split { | |||
| 4408 | print "DEBUG: _Recur_Split\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4409 | my($recur)=@_; | |||
| 4410 | my(@ret,@tmp); | |||
| 4411 | ||||
| 4412 | my($R) = '(\*?(?:[-,0-9]+[:\*]){6}[-,0-9]+)'; | |||
| 4413 | my($F) = '(?:\*([^*]*))'; | |||
| 4414 | my($DB,$D0,$D1); | |||
| 4415 | $DB=$D0=$D1=$F; | |||
| 4416 | ||||
| 4417 | if ($recur =~ /^$R$F?$DB?$D0?$D1?$/) { | |||
| 4418 | @ret=($1,$2,$3,$4,$5); | |||
| 4419 | @tmp=split(/\*/,shift(@ret)); | |||
| 4420 | return () if ($#tmp>1); | |||
| 4421 | return (@tmp,"",@ret) if ($#tmp==0); | |||
| 4422 | return (@tmp,@ret); | |||
| 4423 | } | |||
| 4424 | return (); | |||
| 4425 | } | |||
| 4426 | ||||
| 4427 | # This checks a date. If it is valid, it splits it and returns the elements. | |||
| 4428 | # | |||
| 4429 | # The optional second argument says 'I really expect this to be a | |||
| 4430 | # valid Date::Manip object, please throw an exception if it is not'. | |||
| 4431 | # Otherwise, if the date passed in is undef or '', a regular | |||
| 4432 | # expression for the date is returned; if the string is nonempty but | |||
| 4433 | # still not valid, () is returned. | |||
| 4434 | # | |||
| 4435 | sub _Date_Split { | |||
| 4436 | print "DEBUG: _Date_Split\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4437 | my($date, $definitely_valid)=@_; | |||
| 4438 | $definitely_valid = 0 if not defined $definitely_valid; | |||
| 4439 | my($ym,$md,$dh,$hmn,$mns)=(); | |||
| 4440 | my($y)='(\d{4})'; | |||
| 4441 | my($m)='(0[1-9]|1[0-2])'; | |||
| 4442 | my($d)='(0[1-9]|[1-2][0-9]|3[0-1])'; | |||
| 4443 | my($h)='([0-1][0-9]|2[0-3])'; | |||
| 4444 | my($mn)='([0-5][0-9])'; | |||
| 4445 | my($s)=$mn; | |||
| 4446 | ||||
| 4447 | if ($Cnf{"Internal"} == 0) { | |||
| 4448 | $ym=$md=$dh=""; | |||
| 4449 | $hmn=$mns=":"; | |||
| 4450 | ||||
| 4451 | } elsif ($Cnf{"Internal"} == 1) { | |||
| 4452 | $ym=$md=$dh=$hmn=$mns=""; | |||
| 4453 | ||||
| 4454 | } elsif ($Cnf{"Internal"} == 2) { | |||
| 4455 | $ym=$md="-"; | |||
| 4456 | $dh=" "; | |||
| 4457 | $hmn=$mns=":"; | |||
| 4458 | ||||
| 4459 | } else { | |||
| 4460 | confess "ERROR: Invalid internal format in _Date_Split.\n"; | |||
| 4461 | } | |||
| 4462 | ||||
| 4463 | my($t)="^$y$ym$m$md$d$dh$h$hmn$mn$mns$s\$"; | |||
| 4464 | ||||
| 4465 | if (not defined $date or $date eq '') { | |||
| 4466 | if ($definitely_valid) { | |||
| 4467 | die "bad date '$date'"; | |||
| 4468 | } else { | |||
| 4469 | return $t; | |||
| 4470 | } | |||
| 4471 | } | |||
| 4472 | ||||
| 4473 | if ($date =~ /$t/) { | |||
| 4474 | ($y,$m,$d,$h,$mn,$s)=($1,$2,$3,$4,$5,$6); | |||
| 4475 | my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 4476 | $d_in_m[2]=29 if (Date_LeapYear($y)); | |||
| 4477 | if ($d>$d_in_m[$m]) { | |||
| 4478 | my $msg = "invalid date $date: day $d of month $m, but only $d_in_m[$m] days in that month"; | |||
| 4479 | if ($definitely_valid) { | |||
| 4480 | die $msg; | |||
| 4481 | } | |||
| 4482 | else { | |||
| 4483 | warn $msg; | |||
| 4484 | return (); | |||
| 4485 | } | |||
| 4486 | } | |||
| 4487 | return ($y,$m,$d,$h,$mn,$s); | |||
| 4488 | } | |||
| 4489 | ||||
| 4490 | if ($definitely_valid) { | |||
| 4491 | die "invalid date $date: doesn't match regexp $t"; | |||
| 4492 | } | |||
| 4493 | return (); | |||
| 4494 | } | |||
| 4495 | ||||
| 4496 | # This returns the date easter occurs on for a given year as ($month,$day). | |||
| 4497 | # This is from the Calendar FAQ. | |||
| 4498 | sub _Date_Easter { | |||
| 4499 | my($y)=@_; | |||
| 4500 | $y=_Date_FixYear($y) if (length($y)==2); | |||
| 4501 | ||||
| 4502 | my($c) = $y/100; | |||
| 4503 | my($g) = $y % 19; | |||
| 4504 | my($k) = ($c-17)/25; | |||
| 4505 | my($i) = ($c - $c/4 - ($c-$k)/3 + 19*$g + 15) % 30; | |||
| 4506 | $i = $i - ($i/28)*(1 - ($i/28)*(29/($i+1))*((21-$g)/11)); | |||
| 4507 | my($j) = ($y + $y/4 + $i + 2 - $c + $c/4) % 7; | |||
| 4508 | my($l) = $i-$j; | |||
| 4509 | my($m) = 3 + ($l+40)/44; | |||
| 4510 | my($d) = $l + 28 - 31*($m/4); | |||
| 4511 | return ($m,$d); | |||
| 4512 | } | |||
| 4513 | ||||
| 4514 | # This takes a list of years, months, WeekOfMonth's, and DayOfWeek's, and | |||
| 4515 | # returns a list of dates. Optionally, a list of dates can be passed in as | |||
| 4516 | # the 1st argument (with the 2nd argument the null list) and the year/month | |||
| 4517 | # of these will be used. | |||
| 4518 | sub _Date_Recur_WoM { | |||
| 4519 | my($y,$m,$w,$d)=@_; | |||
| 4520 | my(@y)=@$y; | |||
| 4521 | my(@m)=@$m; | |||
| 4522 | my(@w)=@$w; | |||
| 4523 | my(@d)=@$d; | |||
| 4524 | my($date0,$date1,@tmp,@date,$d0,$d1,@tmp2)=(); | |||
| 4525 | ||||
| 4526 | if (@m) { | |||
| 4527 | foreach $m (@m) { | |||
| 4528 | return () if (! _IsInt($m,1,12)); | |||
| 4529 | } | |||
| 4530 | ||||
| 4531 | @tmp=@tmp2=(); | |||
| 4532 | foreach $y (@y) { | |||
| 4533 | foreach $m (@m) { | |||
| 4534 | push(@tmp,$y); | |||
| 4535 | push(@tmp2,$m); | |||
| 4536 | } | |||
| 4537 | } | |||
| 4538 | ||||
| 4539 | @y=@tmp; | |||
| 4540 | @m=@tmp2; | |||
| 4541 | ||||
| 4542 | } else { | |||
| 4543 | foreach $d0 (@y) { | |||
| 4544 | @tmp=_Date_Split($d0); | |||
| 4545 | return () if (! @tmp); | |||
| 4546 | push(@tmp2,$tmp[0]); | |||
| 4547 | push(@m,$tmp[1]); | |||
| 4548 | } | |||
| 4549 | @y=@tmp2; | |||
| 4550 | } | |||
| 4551 | ||||
| 4552 | return () if (! @w); | |||
| 4553 | foreach $w (@w) { | |||
| 4554 | return () if ($w==0 || ! _IsInt($w,-5,5)); | |||
| 4555 | } | |||
| 4556 | ||||
| 4557 | if (@d) { | |||
| 4558 | foreach $d (@d) { | |||
| 4559 | return () if ($d==0 || ! _IsInt($d,-7,7)); | |||
| 4560 | $d += 8 if ($d < 0); | |||
| 4561 | } | |||
| 4562 | } | |||
| 4563 | ||||
| 4564 | @date=(); | |||
| 4565 | foreach $y (@y) { | |||
| 4566 | $m=shift(@m); | |||
| 4567 | ||||
| 4568 | # Find 1st day of this month and next month | |||
| 4569 | $date0=_Date_Join($y,$m,1,0,0,0); | |||
| 4570 | $date1=_DateCalc_DateDelta($date0,"+0:1:0:0:0:0:0"); | |||
| 4571 | ||||
| 4572 | foreach $d (@d) { | |||
| 4573 | # Find 1st occurence of DOW (in both months) | |||
| 4574 | $d0=Date_GetNext($date0,$d,1); | |||
| 4575 | $d1=Date_GetNext($date1,$d,1); | |||
| 4576 | ||||
| 4577 | @tmp=(); | |||
| 4578 | while (Date_Cmp($d0,$d1)<0) { | |||
| 4579 | push(@tmp,$d0); | |||
| 4580 | $d0=_DateCalc_DateDelta($d0,"+0:0:1:0:0:0:0"); | |||
| 4581 | } | |||
| 4582 | ||||
| 4583 | @tmp2=(); | |||
| 4584 | foreach $w (@w) { | |||
| 4585 | if ($w>0) { | |||
| 4586 | next if ($w > $#tmp+1); | |||
| 4587 | push(@tmp2,$tmp[$w-1]); | |||
| 4588 | } else { | |||
| 4589 | next if (-$w > $#tmp+1); | |||
| 4590 | push(@tmp2,$tmp[$#tmp+1+$w]); | |||
| 4591 | } | |||
| 4592 | } | |||
| 4593 | @tmp2=sort { Date_Cmp($a,$b) } @tmp2; | |||
| 4594 | push(@date,@tmp2); | |||
| 4595 | } | |||
| 4596 | } | |||
| 4597 | ||||
| 4598 | @date; | |||
| 4599 | } | |||
| 4600 | ||||
| 4601 | # This returns a sorted list of dates formed by adding/subtracting | |||
| 4602 | # $delta to $dateb in the range $date0<=$d<$dateb. The first date in | |||
| 4603 | # the list is actually the first date<$date0 and the last date in the | |||
| 4604 | # list is the first date>=$date1 (because sometimes the set part will | |||
| 4605 | # move the date back into the range). | |||
| 4606 | sub _Date_Recur { | |||
| 4607 | my($date0,$date1,$dateb,$delta)=@_; | |||
| 4608 | my(@ret,$d)=(); | |||
| 4609 | ||||
| 4610 | while (Date_Cmp($dateb,$date0)<0) { | |||
| 4611 | $dateb=_DateCalc_DateDelta($dateb,$delta); | |||
| 4612 | } | |||
| 4613 | while (Date_Cmp($dateb,$date1)>=0) { | |||
| 4614 | $dateb=_DateCalc_DateDelta($dateb,"-$delta"); | |||
| 4615 | } | |||
| 4616 | ||||
| 4617 | # Add the dates $date0..$dateb | |||
| 4618 | $d=$dateb; | |||
| 4619 | while (Date_Cmp($d,$date0)>=0) { | |||
| 4620 | unshift(@ret,$d); | |||
| 4621 | $d=_DateCalc_DateDelta($d,"-$delta"); | |||
| 4622 | } | |||
| 4623 | # Add the first date earler than the range | |||
| 4624 | unshift(@ret,$d); | |||
| 4625 | ||||
| 4626 | # Add the dates $dateb..$date1 | |||
| 4627 | $d=_DateCalc_DateDelta($dateb,$delta); | |||
| 4628 | while (Date_Cmp($d,$date1)<0) { | |||
| 4629 | push(@ret,$d); | |||
| 4630 | $d=_DateCalc_DateDelta($d,$delta); | |||
| 4631 | } | |||
| 4632 | # Add the first date later than the range | |||
| 4633 | push(@ret,$d); | |||
| 4634 | ||||
| 4635 | @ret; | |||
| 4636 | } | |||
| 4637 | ||||
| 4638 | # This sets the values in each date of a recurrence. | |||
| 4639 | # | |||
| 4640 | # $h,$m,$s can each be values or lists "1-2,4". If any are equal to "-1", | |||
| 4641 | # they are not set (and none of the larger elements are set). | |||
| 4642 | sub _Date_RecurSetTime { | |||
| 4643 | my($date0,$date1,$dates,$h,$m,$s)=@_; | |||
| 4644 | my(@dates)=@$dates; | |||
| 4645 | my(@h,@m,@s,$date,@tmp)=(); | |||
| 4646 | ||||
| 4647 | $m="-1" if ($s eq "-1"); | |||
| 4648 | $h="-1" if ($m eq "-1"); | |||
| 4649 | ||||
| 4650 | if ($h ne "-1") { | |||
| 4651 | @h=_ReturnList($h); | |||
| 4652 | return () if ! (@h); | |||
| 4653 | @h=sort { $a<=>$b } (@h); | |||
| 4654 | ||||
| 4655 | @tmp=(); | |||
| 4656 | foreach $date (@dates) { | |||
| 4657 | foreach $h (@h) { | |||
| 4658 | push(@tmp,Date_SetDateField($date,"h",$h,1)); | |||
| 4659 | } | |||
| 4660 | } | |||
| 4661 | @dates=@tmp; | |||
| 4662 | } | |||
| 4663 | ||||
| 4664 | if ($m ne "-1") { | |||
| 4665 | @m=_ReturnList($m); | |||
| 4666 | return () if ! (@m); | |||
| 4667 | @m=sort { $a<=>$b } (@m); | |||
| 4668 | ||||
| 4669 | @tmp=(); | |||
| 4670 | foreach $date (@dates) { | |||
| 4671 | foreach $m (@m) { | |||
| 4672 | push(@tmp,Date_SetDateField($date,"mn",$m,1)); | |||
| 4673 | } | |||
| 4674 | } | |||
| 4675 | @dates=@tmp; | |||
| 4676 | } | |||
| 4677 | ||||
| 4678 | if ($s ne "-1") { | |||
| 4679 | @s=_ReturnList($s); | |||
| 4680 | return () if ! (@s); | |||
| 4681 | @s=sort { $a<=>$b } (@s); | |||
| 4682 | ||||
| 4683 | @tmp=(); | |||
| 4684 | foreach $date (@dates) { | |||
| 4685 | foreach $s (@s) { | |||
| 4686 | push(@tmp,Date_SetDateField($date,"s",$s,1)); | |||
| 4687 | } | |||
| 4688 | } | |||
| 4689 | @dates=@tmp; | |||
| 4690 | } | |||
| 4691 | ||||
| 4692 | @tmp=(); | |||
| 4693 | foreach $date (@dates) { | |||
| 4694 | push(@tmp,$date) if (Date_Cmp($date,$date0)>=0 && | |||
| 4695 | Date_Cmp($date,$date1)<0 && | |||
| 4696 | _Date_Split($date)); | |||
| 4697 | } | |||
| 4698 | ||||
| 4699 | @tmp; | |||
| 4700 | } | |||
| 4701 | ||||
| 4702 | sub _DateCalc_DateDate { | |||
| 4703 | print "DEBUG: _DateCalc_DateDate\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4704 | my($D1,$D2,$mode)=@_; | |||
| 4705 | my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 4706 | $mode=0 if (! defined $mode); | |||
| 4707 | ||||
| 4708 | # Exact mode | |||
| 4709 | if ($mode==0) { | |||
| 4710 | my($y1,$m1,$d1,$h1,$mn1,$s1)=_Date_Split($D1, 1); | |||
| 4711 | my($y2,$m2,$d2,$h2,$mn2,$s2)=_Date_Split($D2, 1); | |||
| 4712 | my($i,@delta,$d,$delta,$y)=(); | |||
| 4713 | ||||
| 4714 | # form the delta for hour/min/sec | |||
| 4715 | $delta[4]=$h2-$h1; | |||
| 4716 | $delta[5]=$mn2-$mn1; | |||
| 4717 | $delta[6]=$s2-$s1; | |||
| 4718 | ||||
| 4719 | # form the delta for yr/mon/day | |||
| 4720 | $delta[0]=$delta[1]=0; | |||
| 4721 | $d=0; | |||
| 4722 | if ($y2>$y1) { | |||
| 4723 | $d=Date_DaysInYear($y1) - Date_DayOfYear($m1,$d1,$y1); | |||
| 4724 | $d+=Date_DayOfYear($m2,$d2,$y2); | |||
| 4725 | for ($y=$y1+1; $y<$y2; $y++) { | |||
| 4726 | $d+= Date_DaysInYear($y); | |||
| 4727 | } | |||
| 4728 | } elsif ($y2<$y1) { | |||
| 4729 | $d=Date_DaysInYear($y2) - Date_DayOfYear($m2,$d2,$y2); | |||
| 4730 | $d+=Date_DayOfYear($m1,$d1,$y1); | |||
| 4731 | for ($y=$y2+1; $y<$y1; $y++) { | |||
| 4732 | $d+= Date_DaysInYear($y); | |||
| 4733 | } | |||
| 4734 | $d *= -1; | |||
| 4735 | } else { | |||
| 4736 | $d=Date_DayOfYear($m2,$d2,$y2) - Date_DayOfYear($m1,$d1,$y1); | |||
| 4737 | } | |||
| 4738 | $delta[2]=0; | |||
| 4739 | $delta[3]=$d; | |||
| 4740 | ||||
| 4741 | for ($i=0; $i<7; $i++) { | |||
| 4742 | $delta[$i]="+".$delta[$i] if ($delta[$i]>=0); | |||
| 4743 | } | |||
| 4744 | ||||
| 4745 | $delta=join(":",@delta); | |||
| 4746 | $delta=_Delta_Normalize($delta,0); | |||
| 4747 | return $delta; | |||
| 4748 | } | |||
| 4749 | ||||
| 4750 | my($date1,$date2)=($D1,$D2); | |||
| 4751 | my($tmp,$sign,$err,@tmp)=(); | |||
| 4752 | ||||
| 4753 | # make sure both are work days | |||
| 4754 | if ($mode==2 || $mode==3) { | |||
| 4755 | $date1=Date_NextWorkDay($date1,0,1); | |||
| 4756 | $date2=Date_NextWorkDay($date2,0,1); | |||
| 4757 | } | |||
| 4758 | ||||
| 4759 | # make sure date1 comes before date2 | |||
| 4760 | if (Date_Cmp($date1,$date2)>0) { | |||
| 4761 | $sign="-"; | |||
| 4762 | $tmp=$date1; | |||
| 4763 | $date1=$date2; | |||
| 4764 | $date2=$tmp; | |||
| 4765 | } else { | |||
| 4766 | $sign="+"; | |||
| 4767 | } | |||
| 4768 | if (Date_Cmp($date1,$date2)==0) { | |||
| 4769 | return "+0:+0:+0:+0:+0:+0:+0" if ($Cnf{"DeltaSigns"}); | |||
| 4770 | return "+0:0:0:0:0:0:0"; | |||
| 4771 | } | |||
| 4772 | ||||
| 4773 | my($y1,$m1,$d1,$h1,$mn1,$s1)=_Date_Split($date1, 1); | |||
| 4774 | my($y2,$m2,$d2,$h2,$mn2,$s2)=_Date_Split($date2, 1); | |||
| 4775 | my($dy,$dm,$dw,$dd,$dh,$dmn,$ds,$ddd)=(0,0,0,0,0,0,0,0); | |||
| 4776 | ||||
| 4777 | if ($mode != 3) { | |||
| 4778 | ||||
| 4779 | # Do years | |||
| 4780 | $dy=$y2-$y1; | |||
| 4781 | $dm=0; | |||
| 4782 | if ($dy>0) { | |||
| 4783 | $tmp=_DateCalc_DateDelta($date1,"+$dy:0:0:0:0:0:0",\$err,0); | |||
| 4784 | if (Date_Cmp($tmp,$date2)>0) { | |||
| 4785 | $dy--; | |||
| 4786 | $tmp=$date1; | |||
| 4787 | $tmp=_DateCalc_DateDelta($date1,"+$dy:0:0:0:0:0:0",\$err,0) | |||
| 4788 | if ($dy>0); | |||
| 4789 | $dm=12; | |||
| 4790 | } | |||
| 4791 | $date1=$tmp; | |||
| 4792 | } | |||
| 4793 | ||||
| 4794 | # Do months | |||
| 4795 | $dm+=$m2-$m1; | |||
| 4796 | if ($dm>0) { | |||
| 4797 | $tmp=_DateCalc_DateDelta($date1,"+0:$dm:0:0:0:0:0",\$err,0); | |||
| 4798 | if (Date_Cmp($tmp,$date2)>0) { | |||
| 4799 | $dm--; | |||
| 4800 | $tmp=$date1; | |||
| 4801 | $tmp=_DateCalc_DateDelta($date1,"+0:$dm:0:0:0:0:0",\$err,0) | |||
| 4802 | if ($dm>0); | |||
| 4803 | } | |||
| 4804 | $date1=$tmp; | |||
| 4805 | } | |||
| 4806 | ||||
| 4807 | # At this point, check to see that we're on a business day again so that | |||
| 4808 | # Aug 3 (Monday) -> Sep 3 (Sunday) -> Sep 4 (Monday) = 1 month | |||
| 4809 | if ($mode==2) { | |||
| 4810 | if (! Date_IsWorkDay($date1,0)) { | |||
| 4811 | $date1=Date_NextWorkDay($date1,0,1); | |||
| 4812 | } | |||
| 4813 | } | |||
| 4814 | } | |||
| 4815 | ||||
| 4816 | # Do days | |||
| 4817 | if ($mode==2 || $mode==3) { | |||
| 4818 | $dd=0; | |||
| 4819 | while (1) { | |||
| 4820 | $tmp=Date_NextWorkDay($date1,1,1); | |||
| 4821 | if (Date_Cmp($tmp,$date2)<=0) { | |||
| 4822 | $dd++; | |||
| 4823 | $date1=$tmp; | |||
| 4824 | } else { | |||
| 4825 | last; | |||
| 4826 | } | |||
| 4827 | } | |||
| 4828 | ||||
| 4829 | } else { | |||
| 4830 | ($y1,$m1,$d1)=( _Date_Split($date1, 1) )[0..2]; | |||
| 4831 | $dd=0; | |||
| 4832 | # If we're jumping across months, set $d1 to the first of the next month | |||
| 4833 | # (or possibly the 0th of next month which is equivalent to the last day | |||
| 4834 | # of this month) | |||
| 4835 | if ($m1!=$m2) { | |||
| 4836 | $d_in_m[2]=29 if (Date_LeapYear($y1)); | |||
| 4837 | $dd=$d_in_m[$m1]-$d1+1; | |||
| 4838 | $d1=1; | |||
| 4839 | $tmp=_DateCalc_DateDelta($date1,"+0:0:0:$dd:0:0:0",\$err,0); | |||
| 4840 | if (Date_Cmp($tmp,$date2)>0) { | |||
| 4841 | $dd--; | |||
| 4842 | $d1--; | |||
| 4843 | $tmp=_DateCalc_DateDelta($date1,"+0:0:0:$dd:0:0:0",\$err,0); | |||
| 4844 | } | |||
| 4845 | $date1=$tmp; | |||
| 4846 | } | |||
| 4847 | ||||
| 4848 | $ddd=0; | |||
| 4849 | if ($d1<$d2) { | |||
| 4850 | $ddd=$d2-$d1; | |||
| 4851 | $tmp=_DateCalc_DateDelta($date1,"+0:0:0:$ddd:0:0:0",\$err,0); | |||
| 4852 | if (Date_Cmp($tmp,$date2)>0) { | |||
| 4853 | $ddd--; | |||
| 4854 | $tmp=_DateCalc_DateDelta($date1,"+0:0:0:$ddd:0:0:0",\$err,0); | |||
| 4855 | } | |||
| 4856 | $date1=$tmp; | |||
| 4857 | } | |||
| 4858 | $dd+=$ddd; | |||
| 4859 | } | |||
| 4860 | ||||
| 4861 | # in business mode, make sure h1 comes before h2 (if not find delta between | |||
| 4862 | # now and end of day and move to start of next business day) | |||
| 4863 | $d1=( _Date_Split($date1, 1) )[2]; | |||
| 4864 | $dh=$dmn=$ds=0; | |||
| 4865 | if ($mode==2 || $mode==3 and $d1 != $d2) { | |||
| 4866 | $tmp=Date_SetTime($date1,$Cnf{"WorkDayEnd"}); | |||
| 4867 | $tmp=_DateCalc_DateDelta($tmp,"+0:0:0:0:0:1:0") | |||
| 4868 | if ($Cnf{"WorkDay24Hr"}); | |||
| 4869 | $tmp=_DateCalc_DateDate($date1,$tmp,0); | |||
| 4870 | ($tmp,$tmp,$tmp,$tmp,$dh,$dmn,$ds)=_Delta_Split($tmp); | |||
| 4871 | $date1=Date_NextWorkDay($date1,1,0); | |||
| 4872 | $date1=Date_SetTime($date1,$Cnf{"WorkDayBeg"}); | |||
| 4873 | $d1=( _Date_Split($date1, 1) )[2]; | |||
| 4874 | confess "ERROR: DateCalc DateDate Business.\n" if ($d1 != $d2); | |||
| 4875 | } | |||
| 4876 | ||||
| 4877 | # Hours, minutes, seconds | |||
| 4878 | $tmp=_DateCalc_DateDate($date1,$date2,0); | |||
| 4879 | @tmp=_Delta_Split($tmp); | |||
| 4880 | $dh += $tmp[4]; | |||
| 4881 | $dmn += $tmp[5]; | |||
| 4882 | $ds += $tmp[6]; | |||
| 4883 | ||||
| 4884 | $tmp="$sign$dy:$dm:0:$dd:$dh:$dmn:$ds"; | |||
| 4885 | _Delta_Normalize($tmp,$mode); | |||
| 4886 | } | |||
| 4887 | ||||
| 4888 | sub _DateCalc_DeltaDelta { | |||
| 4889 | print "DEBUG: _DateCalc_DeltaDelta\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4890 | my($D1,$D2,$mode)=@_; | |||
| 4891 | my(@delta1,@delta2,$i,$delta,@delta)=(); | |||
| 4892 | $mode=0 if (! defined $mode); | |||
| 4893 | ||||
| 4894 | @delta1=_Delta_Split($D1); | |||
| 4895 | @delta2=_Delta_Split($D2); | |||
| 4896 | for ($i=0; $i<7; $i++) { | |||
| 4897 | $delta[$i]=$delta1[$i]+$delta2[$i]; | |||
| 4898 | $delta[$i]="+".$delta[$i] if ($delta[$i]>=0); | |||
| 4899 | } | |||
| 4900 | ||||
| 4901 | $delta=join(":",@delta); | |||
| 4902 | $delta=_Delta_Normalize($delta,$mode); | |||
| 4903 | return $delta; | |||
| 4904 | } | |||
| 4905 | ||||
| 4906 | sub _DateCalc_DateDelta { | |||
| 4907 | print "DEBUG: _DateCalc_DateDelta\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 4908 | my($D1,$D2,$errref,$mode)=@_; | |||
| 4909 | my($date)=(); | |||
| 4910 | my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 4911 | my($h1,$m1,$h2,$m2,$len,$hh,$mm)=(); | |||
| 4912 | $mode=0 if (! defined $mode); | |||
| 4913 | ||||
| 4914 | if ($mode==2 || $mode==3) { | |||
| 4915 | $h1=$Curr{"WDBh"}; | |||
| 4916 | $m1=$Curr{"WDBm"}; | |||
| 4917 | $h2=$Curr{"WDEh"}; | |||
| 4918 | $m2=$Curr{"WDEm"}; | |||
| 4919 | $hh=$h2-$h1; | |||
| 4920 | $mm=$m2-$m1; | |||
| 4921 | if ($mm<0) { | |||
| 4922 | $hh--; | |||
| 4923 | $mm+=60; | |||
| 4924 | } | |||
| 4925 | } | |||
| 4926 | ||||
| 4927 | # Date, delta | |||
| 4928 | my($y,$m,$d,$h,$mn,$s)=_Date_Split($D1, 1); | |||
| 4929 | my($dy,$dm,$dw,$dd,$dh,$dmn,$ds)=_Delta_Split($D2); | |||
| 4930 | ||||
| 4931 | # do the month/year part | |||
| 4932 | $y+=$dy; | |||
| 4933 | while (length($y)<4) { | |||
| 4934 | $y = "0$y"; | |||
| 4935 | } | |||
| 4936 | _ModuloAddition(-12,$dm,\$m,\$y); # -12 means 1-12 instead of 0-11 | |||
| 4937 | $d_in_m[2]=29 if (Date_LeapYear($y)); | |||
| 4938 | ||||
| 4939 | # if we have gone past the last day of a month, move the date back to | |||
| 4940 | # the last day of the month | |||
| 4941 | if ($d>$d_in_m[$m]) { | |||
| 4942 | $d=$d_in_m[$m]; | |||
| 4943 | } | |||
| 4944 | ||||
| 4945 | # do the week part | |||
| 4946 | if ($mode==0 || $mode==1) { | |||
| 4947 | $dd += $dw*7; | |||
| 4948 | } else { | |||
| 4949 | $date=_DateCalc_DateDelta(_Date_Join($y,$m,$d,$h,$mn,$s), | |||
| 4950 | "+0:0:$dw:0:0:0:0",0); | |||
| 4951 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date, 1); | |||
| 4952 | } | |||
| 4953 | ||||
| 4954 | # in business mode, set the day to a work day at this point so the h/mn/s | |||
| 4955 | # stuff will work out | |||
| 4956 | if ($mode==2 || $mode==3) { | |||
| 4957 | $d=$d_in_m[$m] if ($d>$d_in_m[$m]); | |||
| 4958 | $date=Date_NextWorkDay(_Date_Join($y,$m,$d,$h,$mn,$s),0,1); | |||
| 4959 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date, 1); | |||
| 4960 | } | |||
| 4961 | ||||
| 4962 | # seconds, minutes, hours | |||
| 4963 | _ModuloAddition(60,$ds,\$s,\$mn); | |||
| 4964 | if ($mode==2 || $mode==3) { | |||
| 4965 | while (1) { | |||
| 4966 | _ModuloAddition(60,$dmn,\$mn,\$h); | |||
| 4967 | $h+= $dh; | |||
| 4968 | ||||
| 4969 | if ($h>$h2 or $h==$h2 && $mn>$m2) { | |||
| 4970 | $dh=$h-$h2; | |||
| 4971 | $dmn=$mn-$m2; | |||
| 4972 | $h=$h1; | |||
| 4973 | $mn=$m1; | |||
| 4974 | $dd++; | |||
| 4975 | ||||
| 4976 | } elsif ($h<$h1 or $h==$h1 && $mn<$m1) { | |||
| 4977 | $dh=$h-$h1; | |||
| 4978 | $dmn=$m1-$mn; | |||
| 4979 | $h=$h2; | |||
| 4980 | $mn=$m2; | |||
| 4981 | $dd--; | |||
| 4982 | ||||
| 4983 | } elsif ($h==$h2 && $mn==$m2) { | |||
| 4984 | $dd++; | |||
| 4985 | $dh=-$hh; | |||
| 4986 | $dmn=-$mm; | |||
| 4987 | ||||
| 4988 | } else { | |||
| 4989 | last; | |||
| 4990 | } | |||
| 4991 | } | |||
| 4992 | ||||
| 4993 | } else { | |||
| 4994 | _ModuloAddition(60,$dmn,\$mn,\$h); | |||
| 4995 | _ModuloAddition(24,$dh,\$h,\$d); | |||
| 4996 | } | |||
| 4997 | ||||
| 4998 | # If we have just gone past the last day of the month, we need to make | |||
| 4999 | # up for this: | |||
| 5000 | if ($d>$d_in_m[$m]) { | |||
| 5001 | $dd+= $d-$d_in_m[$m]; | |||
| 5002 | $d=$d_in_m[$m]; | |||
| 5003 | } | |||
| 5004 | ||||
| 5005 | # days | |||
| 5006 | if ($mode==2 || $mode==3) { | |||
| 5007 | if ($dd>=0) { | |||
| 5008 | $date=Date_NextWorkDay(_Date_Join($y,$m,$d,$h,$mn,$s),$dd,1); | |||
| 5009 | } else { | |||
| 5010 | $date=Date_PrevWorkDay(_Date_Join($y,$m,$d,$h,$mn,$s),-$dd,1); | |||
| 5011 | } | |||
| 5012 | ($y,$m,$d,$h,$mn,$s)=_Date_Split($date, 1); | |||
| 5013 | ||||
| 5014 | } else { | |||
| 5015 | $d_in_m[2]=29 if (Date_LeapYear($y)); | |||
| 5016 | $d=$d_in_m[$m] if ($d>$d_in_m[$m]); | |||
| 5017 | $d += $dd; | |||
| 5018 | while ($d<1) { | |||
| 5019 | $m--; | |||
| 5020 | if ($m==0) { | |||
| 5021 | $m=12; | |||
| 5022 | $y--; | |||
| 5023 | if (Date_LeapYear($y)) { | |||
| 5024 | $d_in_m[2]=29; | |||
| 5025 | } else { | |||
| 5026 | $d_in_m[2]=28; | |||
| 5027 | } | |||
| 5028 | } | |||
| 5029 | $d += $d_in_m[$m]; | |||
| 5030 | } | |||
| 5031 | while ($d>$d_in_m[$m]) { | |||
| 5032 | $d -= $d_in_m[$m]; | |||
| 5033 | $m++; | |||
| 5034 | if ($m==13) { | |||
| 5035 | $m=1; | |||
| 5036 | $y++; | |||
| 5037 | if (Date_LeapYear($y)) { | |||
| 5038 | $d_in_m[2]=29; | |||
| 5039 | } else { | |||
| 5040 | $d_in_m[2]=28; | |||
| 5041 | } | |||
| 5042 | } | |||
| 5043 | } | |||
| 5044 | } | |||
| 5045 | ||||
| 5046 | if ($y<0 or $y>9999) { | |||
| 5047 | $$errref=3; | |||
| 5048 | return; | |||
| 5049 | } | |||
| 5050 | _Date_Join($y,$m,$d,$h,$mn,$s); | |||
| 5051 | } | |||
| 5052 | ||||
| 5053 | sub _Date_UpdateHolidays { | |||
| 5054 | print "DEBUG: _Date_UpdateHolidays\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5055 | my($year)=@_; | |||
| 5056 | $Holiday{"year"}=$year; | |||
| 5057 | $Holiday{"dates"}{$year}={}; | |||
| 5058 | ||||
| 5059 | my($date,$delta,$err)=(); | |||
| 5060 | my($key,@tmp,$tmp); | |||
| 5061 | ||||
| 5062 | foreach $key (keys %{ $Holiday{"desc"} }) { | |||
| 5063 | @tmp=_Recur_Split($key); | |||
| 5064 | if (@tmp) { | |||
| 5065 | $tmp=ParseDateString("${year}010100:00:00"); | |||
| 5066 | ($date)=ParseRecur($key,$tmp,$tmp,($year+1)."-01-01"); | |||
| 5067 | next if (! $date); | |||
| 5068 | ||||
| 5069 | } elsif ($key =~ /^(.*)([+-].*)$/) { | |||
| 5070 | # Date +/- Delta | |||
| 5071 | ($date,$delta)=($1,$2); | |||
| 5072 | $tmp=ParseDateString("$date $year"); | |||
| 5073 | if ($tmp) { | |||
| 5074 | $date=$tmp; | |||
| 5075 | } else { | |||
| 5076 | $date=ParseDateString($date); | |||
| 5077 | next if ($date !~ /^$year/); | |||
| 5078 | } | |||
| 5079 | $date=DateCalc($date,$delta,\$err,0); | |||
| 5080 | ||||
| 5081 | } else { | |||
| 5082 | # Date | |||
| 5083 | $date=$key; | |||
| 5084 | $tmp=ParseDateString("$date $year"); | |||
| 5085 | if ($tmp) { | |||
| 5086 | $date=$tmp; | |||
| 5087 | } else { | |||
| 5088 | $date=ParseDateString($date); | |||
| 5089 | next if ($date !~ /^$year/); | |||
| 5090 | } | |||
| 5091 | } | |||
| 5092 | $Holiday{"dates"}{$year}{$date}=$Holiday{"desc"}{$key}; | |||
| 5093 | } | |||
| 5094 | } | |||
| 5095 | ||||
| 5096 | # This sets a Date::Manip config variable. | |||
| 5097 | sub _Date_SetConfigVariable { | |||
| 5098 | print "DEBUG: _Date_SetConfigVariable\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5099 | my($var,$val)=@_; | |||
| 5100 | ||||
| 5101 | # These are most appropriate for command line options instead of in files. | |||
| 5102 | $Cnf{"PathSep"}=$val, return if ($var =~ /^PathSep$/i); | |||
| 5103 | $Cnf{"PersonalCnf"}=$val, return if ($var =~ /^PersonalCnf$/i); | |||
| 5104 | $Cnf{"PersonalCnfPath"}=$val, return if ($var =~ /^PersonalCnfPath$/i); | |||
| 5105 | EraseHolidays(), return if ($var =~ /^EraseHolidays$/i); | |||
| 5106 | $Cnf{"IgnoreGlobalCnf"}=1, return if ($var =~ /^IgnoreGlobalCnf$/i); | |||
| 5107 | $Cnf{"GlobalCnf"}=$val, return if ($var =~ /^GlobalCnf$/i); | |||
| 5108 | ||||
| 5109 | $Curr{"InitLang"}=1, | |||
| 5110 | $Cnf{"Language"}=$val, return if ($var =~ /^Language$/i); | |||
| 5111 | $Cnf{"DateFormat"}=$val, return if ($var =~ /^DateFormat$/i); | |||
| 5112 | $Cnf{"TZ"}=$val, return if ($var =~ /^TZ$/i); | |||
| 5113 | $Cnf{"ConvTZ"}=$val, return if ($var =~ /^ConvTZ$/i); | |||
| 5114 | $Cnf{"Internal"}=$val, return if ($var =~ /^Internal$/i); | |||
| 5115 | $Cnf{"FirstDay"}=$val, return if ($var =~ /^FirstDay$/i); | |||
| 5116 | $Cnf{"WorkWeekBeg"}=$val, return if ($var =~ /^WorkWeekBeg$/i); | |||
| 5117 | $Cnf{"WorkWeekEnd"}=$val, return if ($var =~ /^WorkWeekEnd$/i); | |||
| 5118 | $Cnf{"WorkDayBeg"}=$val, | |||
| 5119 | $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDayBeg$/i); | |||
| 5120 | $Cnf{"WorkDayEnd"}=$val, | |||
| 5121 | $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDayEnd$/i); | |||
| 5122 | $Cnf{"WorkDay24Hr"}=$val, | |||
| 5123 | $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDay24Hr$/i); | |||
| 5124 | $Cnf{"DeltaSigns"}=$val, return if ($var =~ /^DeltaSigns$/i); | |||
| 5125 | $Cnf{"Jan1Week1"}=$val, return if ($var =~ /^Jan1Week1$/i); | |||
| 5126 | $Cnf{"YYtoYYYY"}=$val, return if ($var =~ /^YYtoYYYY$/i); | |||
| 5127 | $Cnf{"UpdateCurrTZ"}=$val, return if ($var =~ /^UpdateCurrTZ$/i); | |||
| 5128 | $Cnf{"IntCharSet"}=$val, return if ($var =~ /^IntCharSet$/i); | |||
| 5129 | $Curr{"DebugVal"}=$val, return if ($var =~ /^Debug$/i); | |||
| 5130 | $Cnf{"TomorrowFirst"}=$val, return if ($var =~ /^TomorrowFirst$/i); | |||
| 5131 | $Cnf{"ForceDate"}=$val, return if ($var =~ /^ForceDate$/i); | |||
| 5132 | $Cnf{"TodayIsMidnight"}=$val, return if ($var =~ /^TodayIsMidnight$/i); | |||
| 5133 | ||||
| 5134 | confess "ERROR: Unknown configuration variable $var in Date::Manip.\n"; | |||
| 5135 | } | |||
| 5136 | ||||
| 5137 | sub EraseHolidays { | |||
| 5138 | print "DEBUG: EraseHolidays\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5139 | ||||
| 5140 | $Cnf{"EraseHolidays"}=0; | |||
| 5141 | delete $Holiday{"list"}; | |||
| 5142 | $Holiday{"list"}={}; | |||
| 5143 | delete $Holiday{"desc"}; | |||
| 5144 | $Holiday{"desc"}={}; | |||
| 5145 | $Holiday{"dates"}={}; | |||
| 5146 | } | |||
| 5147 | ||||
| 5148 | # This returns a pointer to a list of times and events in the format | |||
| 5149 | # [ date [ events ], date, [ events ], ... ] | |||
| 5150 | # where each list of events are events that are in effect at the date | |||
| 5151 | # immediately preceding the list. | |||
| 5152 | # | |||
| 5153 | # This takes either one date or two dates as arguments. | |||
| 5154 | sub _Events_Calc { | |||
| 5155 | print "DEBUG: _Events_Calc\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5156 | ||||
| 5157 | my($date0,$date1)=@_; | |||
| 5158 | ||||
| 5159 | my($tmp); | |||
| 5160 | $date0=ParseDateString($date0); | |||
| 5161 | return undef if (! $date0); | |||
| 5162 | if ($date1) { | |||
| 5163 | $date1=ParseDateString($date1); | |||
| 5164 | if (Date_Cmp($date0,$date1)>0) { | |||
| 5165 | $tmp=$date1; | |||
| 5166 | $date1=$date0; | |||
| 5167 | $date0=$tmp; | |||
| 5168 | } | |||
| 5169 | } else { | |||
| 5170 | $date1=_DateCalc_DateDelta($date0,"+0:0:0:0:0:0:1"); | |||
| 5171 | } | |||
| 5172 | ||||
| 5173 | # | |||
| 5174 | # [ d0,d1,del,name ] => [ d0, d1+del ) | |||
| 5175 | # [ d0,0,del,name ] => [ d0, d0+del ) | |||
| 5176 | # | |||
| 5177 | my(%ret,$d0,$d1,$del,$name,$c0,$c1); | |||
| 5178 | my(@tmp)=@{ $Events{"dates"} }; | |||
| 5179 | DATE: while (@tmp) { | |||
| 5180 | ($d0,$d1,$del,$name)=splice(@tmp,0,4); | |||
| 5181 | $d0=ParseDateString($d0); | |||
| 5182 | $d1=ParseDateString($d1) if ($d1); | |||
| 5183 | $del=ParseDateDelta($del) if ($del); | |||
| 5184 | if ($d1) { | |||
| 5185 | if ($del) { | |||
| 5186 | $d1=_DateCalc_DateDelta($d1,$del); | |||
| 5187 | } | |||
| 5188 | } else { | |||
| 5189 | $d1=_DateCalc_DateDelta($d0,$del); | |||
| 5190 | } | |||
| 5191 | if (Date_Cmp($d0,$d1)>0) { | |||
| 5192 | $tmp=$d1; | |||
| 5193 | $d1=$d0; | |||
| 5194 | $d0=$tmp; | |||
| 5195 | } | |||
| 5196 | # [ date0,date1 ) | |||
| 5197 | # [ d0,d1 ) OR [ d0,d1 ) | |||
| 5198 | next DATE if (Date_Cmp($d1,$date0)<=0 || | |||
| 5199 | Date_Cmp($d0,$date1)>=0); | |||
| 5200 | # [ date0,date1 ) | |||
| 5201 | # [ d0,d1 ) | |||
| 5202 | # [ d0, d1 ) | |||
| 5203 | if (Date_Cmp($d0,$date0)<=0) { | |||
| 5204 | push @{ $ret{$date0} },$name; | |||
| 5205 | push @{ $ret{$d1} },"!$name" if (Date_Cmp($d1,$date1)<0); | |||
| 5206 | next DATE; | |||
| 5207 | } | |||
| 5208 | # [ date0,date1 ) | |||
| 5209 | # [ d0,d1 ) | |||
| 5210 | if (Date_Cmp($d1,$date1)>=0) { | |||
| 5211 | push @{ $ret{$d0} },$name; | |||
| 5212 | next DATE; | |||
| 5213 | } | |||
| 5214 | # [ date0,date1 ) | |||
| 5215 | # [ d0,d1 ) | |||
| 5216 | push @{ $ret{$d0} },$name; | |||
| 5217 | push @{ $ret{$d1} },"!$name"; | |||
| 5218 | } | |||
| 5219 | ||||
| 5220 | # | |||
| 5221 | # [ recur,delta0,delta1,name ] => [ {date-delta0},{date+delta1} ) | |||
| 5222 | # | |||
| 5223 | my($rec,$del0,$del1,@d); | |||
| 5224 | @tmp=@{ $Events{"recur"} }; | |||
| 5225 | RECUR: while (@tmp) { | |||
| 5226 | ($rec,$del0,$del1,$name)=splice(@tmp,0,4); | |||
| 5227 | @d=(); | |||
| 5228 | ||||
| 5229 | } | |||
| 5230 | ||||
| 5231 | # Sort them AND take into account the "!$name" entries. | |||
| 5232 | my(%tmp,$date,@tmp2,@ret); | |||
| 5233 | @d=sort { Date_Cmp($a,$b) } keys %ret; | |||
| 5234 | foreach $date (@d) { | |||
| 5235 | @tmp=@{ $ret{$date} }; | |||
| 5236 | @tmp2=(); | |||
| 5237 | foreach $tmp (@tmp) { | |||
| 5238 | push(@tmp2,$tmp), next if ($tmp =~ /^!/); | |||
| 5239 | $tmp{$tmp}=1; | |||
| 5240 | } | |||
| 5241 | foreach $tmp (@tmp2) { | |||
| 5242 | $tmp =~ s/^!//; | |||
| 5243 | delete $tmp{$tmp}; | |||
| 5244 | } | |||
| 5245 | push(@ret,$date,[ keys %tmp ]); | |||
| 5246 | } | |||
| 5247 | ||||
| 5248 | %tmp = @ret; | |||
| 5249 | @ret = (); | |||
| 5250 | foreach my $d (sort { Date_Cmp($a,$b) } keys %tmp) { | |||
| 5251 | my $e = $tmp{$d}; | |||
| 5252 | push @ret,($d,[ sort @$e ]); | |||
| 5253 | } | |||
| 5254 | return \@ret; | |||
| 5255 | } | |||
| 5256 | ||||
| 5257 | # This parses the raw events list | |||
| 5258 | sub _Events_ParseRaw { | |||
| 5259 | print "DEBUG: _Events_ParseRaw\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5260 | ||||
| 5261 | # Only need to be parsed once | |||
| 5262 | my($force)=@_; | |||
| 5263 | $Events{"parsed"}=0 if ($force); | |||
| 5264 | return if ($Events{"parsed"}); | |||
| 5265 | $Events{"parsed"}=1; | |||
| 5266 | ||||
| 5267 | my(@events)=@{ $Events{"raw"} }; | |||
| 5268 | my($event,$name,@event,$date0,$date1,$tmp,$delta,$recur0,$recur1,@recur,$r, | |||
| 5269 | $recur); | |||
| 5270 | EVENT: while (@events) { | |||
| 5271 | ($event,$name)=splice(@events,0,2); | |||
| 5272 | @event=split(/\s*;\s*/,$event); | |||
| 5273 | ||||
| 5274 | if ($#event == 0) { | |||
| 5275 | ||||
| 5276 | if ($date0=ParseDateString($event[0])) { | |||
| 5277 | # | |||
| 5278 | # date = event | |||
| 5279 | # | |||
| 5280 | $tmp=ParseDateString("$event[0] 00:00:00"); | |||
| 5281 | if ($tmp && $tmp eq $date0) { | |||
| 5282 | $delta="+0:0:0:1:0:0:0"; | |||
| 5283 | } else { | |||
| 5284 | $delta="+0:0:0:0:1:0:0"; | |||
| 5285 | } | |||
| 5286 | push @{ $Events{"dates"} },($date0,0,$delta,$name); | |||
| 5287 | ||||
| 5288 | } elsif ($recur=ParseRecur($event[0])) { | |||
| 5289 | # | |||
| 5290 | # recur = event | |||
| 5291 | # | |||
| 5292 | ($recur0,$recur1)=_Recur_Split($recur); | |||
| 5293 | if ($recur0) { | |||
| 5294 | if ($recur1) { | |||
| 5295 | $r="$recur0:$recur1"; | |||
| 5296 | } else { | |||
| 5297 | $r=$recur0; | |||
| 5298 | } | |||
| 5299 | } else { | |||
| 5300 | $r=$recur1; | |||
| 5301 | } | |||
| 5302 | (@recur)=split(/:/,$r); | |||
| 5303 | if (pop(@recur)==0 && pop(@recur)==0 && pop(@recur)==0) { | |||
| 5304 | $delta="+0:0:0:1:0:0:0"; | |||
| 5305 | } else { | |||
| 5306 | $delta="+0:0:0:0:1:0:0"; | |||
| 5307 | } | |||
| 5308 | push @{ $Events{"recur"} },($recur,0,$delta,$name); | |||
| 5309 | ||||
| 5310 | } else { | |||
| 5311 | # ??? = event | |||
| 5312 | warn "WARNING: illegal event ignored [ @event ]\n"; | |||
| 5313 | next EVENT; | |||
| 5314 | } | |||
| 5315 | ||||
| 5316 | } elsif ($#event == 1) { | |||
| 5317 | ||||
| 5318 | if ($date0=ParseDateString($event[0])) { | |||
| 5319 | ||||
| 5320 | if ($date1=ParseDateString($event[1])) { | |||
| 5321 | # | |||
| 5322 | # date ; date = event | |||
| 5323 | # | |||
| 5324 | $tmp=ParseDateString("$event[1] 00:00:00"); | |||
| 5325 | if ($tmp && $tmp eq $date1) { | |||
| 5326 | $date1=_DateCalc_DateDelta($date1,"+0:0:0:1:0:0:0"); | |||
| 5327 | } | |||
| 5328 | push @{ $Events{"dates"} },($date0,$date1,0,$name); | |||
| 5329 | ||||
| 5330 | } elsif ($delta=ParseDateDelta($event[1])) { | |||
| 5331 | # | |||
| 5332 | # date ; delta = event | |||
| 5333 | # | |||
| 5334 | push @{ $Events{"dates"} },($date0,0,$delta,$name); | |||
| 5335 | ||||
| 5336 | } else { | |||
| 5337 | # date ; ??? = event | |||
| 5338 | warn "WARNING: illegal event ignored [ @event ]\n"; | |||
| 5339 | next EVENT; | |||
| 5340 | } | |||
| 5341 | ||||
| 5342 | } elsif ($recur=ParseRecur($event[0])) { | |||
| 5343 | ||||
| 5344 | if ($delta=ParseDateDelta($event[1])) { | |||
| 5345 | # | |||
| 5346 | # recur ; delta = event | |||
| 5347 | # | |||
| 5348 | push @{ $Events{"recur"} },($recur,0,$delta,$name); | |||
| 5349 | ||||
| 5350 | } else { | |||
| 5351 | # recur ; ??? = event | |||
| 5352 | warn "WARNING: illegal event ignored [ @event ]\n"; | |||
| 5353 | next EVENT; | |||
| 5354 | } | |||
| 5355 | ||||
| 5356 | } else { | |||
| 5357 | # ??? ; ??? = event | |||
| 5358 | warn "WARNING: illegal event ignored [ @event ]\n"; | |||
| 5359 | next EVENT; | |||
| 5360 | } | |||
| 5361 | ||||
| 5362 | } else { | |||
| 5363 | # date ; delta0 ; delta1 = event | |||
| 5364 | # recur ; delta0 ; delta1 = event | |||
| 5365 | # ??? ; ??? ; ??? ... = event | |||
| 5366 | warn "WARNING: illegal event ignored [ @event ]\n"; | |||
| 5367 | next EVENT; | |||
| 5368 | } | |||
| 5369 | } | |||
| 5370 | } | |||
| 5371 | ||||
| 5372 | # This reads an init file. | |||
| 5373 | sub _Date_InitFile { | |||
| 5374 | print "DEBUG: _Date_InitFile\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5375 | my($file)=@_; | |||
| 5376 | my($in)=new IO::File; | |||
| 5377 | local($_)=(); | |||
| 5378 | my($section)="vars"; | |||
| 5379 | my($var,$val,$recur,$name)=(); | |||
| 5380 | ||||
| 5381 | $in->open($file) || return; | |||
| 5382 | while(defined ($_=<$in>)) { | |||
| 5383 | chomp; | |||
| 5384 | s/^\s+//; | |||
| 5385 | s/\s+$//; | |||
| 5386 | next if (! $_ or /^\#/); | |||
| 5387 | ||||
| 5388 | if (/^\*holiday/i) { | |||
| 5389 | $section="holiday"; | |||
| 5390 | EraseHolidays() if ($section =~ /holiday/i && $Cnf{"EraseHolidays"}); | |||
| 5391 | next; | |||
| 5392 | } elsif (/^\*events/i) { | |||
| 5393 | $section="events"; | |||
| 5394 | next; | |||
| 5395 | } | |||
| 5396 | ||||
| 5397 | if ($section =~ /var/i) { | |||
| 5398 | confess "ERROR: invalid Date::Manip config file line.\n $_\n" | |||
| 5399 | if (! /(.*\S)\s*=\s*(.*)$/); | |||
| 5400 | ($var,$val)=($1,$2); | |||
| 5401 | _Date_SetConfigVariable($var,$val); | |||
| 5402 | ||||
| 5403 | } elsif ($section =~ /holiday/i) { | |||
| 5404 | confess "ERROR: invalid Date::Manip config file line.\n $_\n" | |||
| 5405 | if (! /(.*\S)\s*=\s*(.*)$/); | |||
| 5406 | ($recur,$name)=($1,$2); | |||
| 5407 | $name="" if (! defined $name); | |||
| 5408 | $Holiday{"desc"}{$recur}=$name; | |||
| 5409 | ||||
| 5410 | } elsif ($section =~ /events/i) { | |||
| 5411 | confess "ERROR: invalid Date::Manip config file line.\n $_\n" | |||
| 5412 | if (! /(.*\S)\s*=\s*(.*)$/); | |||
| 5413 | ($val,$var)=($1,$2); | |||
| 5414 | push @{ $Events{"raw"} },($val,$var); | |||
| 5415 | ||||
| 5416 | } else { | |||
| 5417 | # A section not currently used by Date::Manip (but may be | |||
| 5418 | # used by some extension to it). | |||
| 5419 | next; | |||
| 5420 | } | |||
| 5421 | } | |||
| 5422 | close($in); | |||
| 5423 | } | |||
| 5424 | ||||
| 5425 | # $flag=_Date_TimeCheck(\$h,\$mn,\$s,\$ampm); | |||
| 5426 | # Returns 1 if any of the fields are bad. All fields are optional, and | |||
| 5427 | # all possible checks are done on the data. If a field is not passed in, | |||
| 5428 | # it is set to default values. If data is missing, appropriate defaults | |||
| 5429 | # are supplied. | |||
| 5430 | sub _Date_TimeCheck { | |||
| 5431 | print "DEBUG: _Date_TimeCheck\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5432 | my($h,$mn,$s,$ampm)=@_; | |||
| 5433 | my($tmp1,$tmp2,$tmp3)=(); | |||
| 5434 | ||||
| 5435 | $$h="" if (! defined $$h); | |||
| 5436 | $$mn="" if (! defined $$mn); | |||
| 5437 | $$s="" if (! defined $$s); | |||
| 5438 | $$ampm="" if (! defined $$ampm); | |||
| 5439 | $$ampm=uc($$ampm) if ($$ampm); | |||
| 5440 | ||||
| 5441 | # Check hour | |||
| 5442 | $tmp1=$Lang{$Cnf{"Language"}}{"AmPm"}; | |||
| 5443 | $tmp2=""; | |||
| 5444 | if ($$ampm =~ /^$tmp1$/i) { | |||
| 5445 | $tmp3=$Lang{$Cnf{"Language"}}{"AM"}; | |||
| 5446 | $tmp2="AM" if ($$ampm =~ /^$tmp3$/i); | |||
| 5447 | $tmp3=$Lang{$Cnf{"Language"}}{"PM"}; | |||
| 5448 | $tmp2="PM" if ($$ampm =~ /^$tmp3$/i); | |||
| 5449 | } elsif ($$ampm) { | |||
| 5450 | return 1; | |||
| 5451 | } | |||
| 5452 | if ($tmp2 eq "AM" || $tmp2 eq "PM") { | |||
| 5453 | $$h="0$$h" if (length($$h)==1); | |||
| 5454 | return 1 if ($$h<1 || $$h>12); | |||
| 5455 | $$h="00" if ($tmp2 eq "AM" and $$h==12); | |||
| 5456 | $$h += 12 if ($tmp2 eq "PM" and $$h!=12); | |||
| 5457 | } else { | |||
| 5458 | $$h="00" if ($$h eq ""); | |||
| 5459 | $$h="0$$h" if (length($$h)==1); | |||
| 5460 | return 1 if (! _IsInt($$h,0,23)); | |||
| 5461 | $tmp2="AM" if ($$h<12); | |||
| 5462 | $tmp2="PM" if ($$h>=12); | |||
| 5463 | } | |||
| 5464 | $$ampm=$Lang{$Cnf{"Language"}}{"AMstr"}; | |||
| 5465 | $$ampm=$Lang{$Cnf{"Language"}}{"PMstr"} if ($tmp2 eq "PM"); | |||
| 5466 | ||||
| 5467 | # Check minutes | |||
| 5468 | $$mn="00" if ($$mn eq ""); | |||
| 5469 | $$mn="0$$mn" if (length($$mn)==1); | |||
| 5470 | return 1 if (! _IsInt($$mn,0,59)); | |||
| 5471 | ||||
| 5472 | # Check seconds | |||
| 5473 | $$s="00" if ($$s eq ""); | |||
| 5474 | $$s="0$$s" if (length($$s)==1); | |||
| 5475 | return 1 if (! _IsInt($$s,0,59)); | |||
| 5476 | ||||
| 5477 | return 0; | |||
| 5478 | } | |||
| 5479 | ||||
| 5480 | # $flag=_Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk); | |||
| 5481 | # Returns 1 if any of the fields are bad. All fields are optional, and | |||
| 5482 | # all possible checks are done on the data. If a field is not passed in, | |||
| 5483 | # it is set to default values. If data is missing, appropriate defaults | |||
| 5484 | # are supplied. | |||
| 5485 | # | |||
| 5486 | # If the flag UpdateHolidays is set, the year is set to | |||
| 5487 | # CurrHolidayYear. | |||
| 5488 | sub _Date_DateCheck { | |||
| 5489 | print "DEBUG: _Date_DateCheck\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5490 | my($y,$m,$d,$h,$mn,$s,$ampm,$wk)=@_; | |||
| 5491 | my($tmp1,$tmp2,$tmp3)=(); | |||
| 5492 | ||||
| 5493 | my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31); | |||
| 5494 | my($curr_y)=$Curr{"Y"}; | |||
| 5495 | my($curr_m)=$Curr{"M"}; | |||
| 5496 | my($curr_d)=$Curr{"D"}; | |||
| 5497 | $$m=1, $$d=1 if (defined $$y and ! defined $$m and ! defined $$d); | |||
| 5498 | $$y="" if (! defined $$y); | |||
| 5499 | $$m="" if (! defined $$m); | |||
| 5500 | $$d="" if (! defined $$d); | |||
| 5501 | $$wk="" if (! defined $$wk); | |||
| 5502 | $$d=$curr_d if ($$y eq "" and $$m eq "" and $$d eq ""); | |||
| 5503 | ||||
| 5504 | # Check year. | |||
| 5505 | $$y=$curr_y if ($$y eq ""); | |||
| 5506 | $$y=_Date_FixYear($$y) if (length($$y)<4); | |||
| 5507 | return 1 if (! _IsInt($$y,0,9999)); | |||
| 5508 | $d_in_m[2]=29 if (Date_LeapYear($$y)); | |||
| 5509 | ||||
| 5510 | # Check month | |||
| 5511 | $$m=$curr_m if ($$m eq ""); | |||
| 5512 | $$m=$Lang{$Cnf{"Language"}}{"MonthH"}{lc($$m)} | |||
| 5513 | if (exists $Lang{$Cnf{"Language"}}{"MonthH"}{lc($$m)}); | |||
| 5514 | $$m="0$$m" if (length($$m)==1); | |||
| 5515 | return 1 if (! _IsInt($$m,1,12)); | |||
| 5516 | ||||
| 5517 | # Check day | |||
| 5518 | $$d="01" if ($$d eq ""); | |||
| 5519 | $$d="0$$d" if (length($$d)==1); | |||
| 5520 | return 1 if (! _IsInt($$d,1,$d_in_m[$$m])); | |||
| 5521 | if ($$wk) { | |||
| 5522 | $tmp1=Date_DayOfWeek($$m,$$d,$$y); | |||
| 5523 | $tmp2=$Lang{$Cnf{"Language"}}{"WeekH"}{lc($$wk)} | |||
| 5524 | if (exists $Lang{$Cnf{"Language"}}{"WeekH"}{lc($$wk)}); | |||
| 5525 | return 1 if ($tmp1 != $tmp2); | |||
| 5526 | } | |||
| 5527 | ||||
| 5528 | return _Date_TimeCheck($h,$mn,$s,$ampm); | |||
| 5529 | } | |||
| 5530 | ||||
| 5531 | # Takes a year in 2 digit form and returns it in 4 digit form | |||
| 5532 | sub _Date_FixYear { | |||
| 5533 | print "DEBUG: _Date_FixYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5534 | my($y)=@_; | |||
| 5535 | my($curr_y)=$Curr{"Y"}; | |||
| 5536 | $y=$curr_y if (! defined $y or ! $y); | |||
| 5537 | return $y if (length($y)==4); | |||
| 5538 | confess "ERROR: Invalid year ($y)\n" if (length($y)!=2); | |||
| 5539 | my($y1,$y2)=(); | |||
| 5540 | ||||
| 5541 | if (lc($Cnf{"YYtoYYYY"}) eq "c") { | |||
| 5542 | $y1=substr($y,0,2); | |||
| 5543 | $y="$y1$y"; | |||
| 5544 | ||||
| 5545 | } elsif ($Cnf{"YYtoYYYY"} =~ /^c(\d{2})$/i) { | |||
| 5546 | $y1=$1; | |||
| 5547 | $y="$y1$y"; | |||
| 5548 | ||||
| 5549 | } elsif ($Cnf{"YYtoYYYY"} =~ /^c(\d{2})(\d{2})$/i) { | |||
| 5550 | $y1="$1$2"; | |||
| 5551 | $y ="$1$y"; | |||
| 5552 | $y += 100 if ($y<$y1); | |||
| 5553 | ||||
| 5554 | } else { | |||
| 5555 | $y1=$curr_y-$Cnf{"YYtoYYYY"}; | |||
| 5556 | $y2=$y1+99; | |||
| 5557 | $y="19$y"; | |||
| 5558 | while ($y<$y1) { | |||
| 5559 | $y+=100; | |||
| 5560 | } | |||
| 5561 | while ($y>$y2) { | |||
| 5562 | $y-=100; | |||
| 5563 | } | |||
| 5564 | } | |||
| 5565 | $y; | |||
| 5566 | } | |||
| 5567 | ||||
| 5568 | # _Date_NthWeekOfYear($y,$n); | |||
| 5569 | # Returns a list of (YYYY,MM,DD) for the 1st day of the Nth week of the | |||
| 5570 | # year. | |||
| 5571 | # _Date_NthWeekOfYear($y,$n,$dow,$flag); | |||
| 5572 | # Returns a list of (YYYY,MM,DD) for the Nth DoW of the year. If flag | |||
| 5573 | # is nil, the first DoW of the year may actually be in the previous | |||
| 5574 | # year (since the 1st week may include days from the previous year). | |||
| 5575 | # If flag is non-nil, the 1st DoW of the year refers to the 1st one | |||
| 5576 | # actually in the year | |||
| 5577 | sub _Date_NthWeekOfYear { | |||
| 5578 | print "DEBUG: _Date_NthWeekOfYear\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5579 | my($y,$n,$dow,$flag)=@_; | |||
| 5580 | my($m,$d,$err,$tmp,$date,%dow)=(); | |||
| 5581 | $y=$Curr{"Y"} if (! defined $y or ! $y); | |||
| 5582 | $n=1 if (! defined $n or $n eq ""); | |||
| 5583 | return () if ($n<0 || $n>53); | |||
| 5584 | if (defined $dow) { | |||
| 5585 | $dow=lc($dow); | |||
| 5586 | %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} }; | |||
| 5587 | $dow=$dow{$dow} if (exists $dow{$dow}); | |||
| 5588 | return () if ($dow<1 || $dow>7); | |||
| 5589 | $flag="" if (! defined $flag); | |||
| 5590 | } else { | |||
| 5591 | $dow=""; | |||
| 5592 | $flag=""; | |||
| 5593 | } | |||
| 5594 | ||||
| 5595 | $y=_Date_FixYear($y) if (length($y)<4); | |||
| 5596 | if ($Cnf{"Jan1Week1"}) { | |||
| 5597 | $date=_Date_Join($y,1,1,0,0,0); | |||
| 5598 | } else { | |||
| 5599 | $date=_Date_Join($y,1,4,0,0,0); | |||
| 5600 | } | |||
| 5601 | $date=Date_GetPrev($date,$Cnf{"FirstDay"},1); | |||
| 5602 | $date=Date_GetNext($date,$dow,1) if ($dow ne ""); | |||
| 5603 | ||||
| 5604 | if ($flag) { | |||
| 5605 | ($tmp)=_Date_Split($date, 1); | |||
| 5606 | $n++ if ($tmp != $y); | |||
| 5607 | } | |||
| 5608 | ||||
| 5609 | if ($n>1) { | |||
| 5610 | $date=_DateCalc_DateDelta($date,"+0:0:". ($n-1) . ":0:0:0:0",\$err,0); | |||
| 5611 | } elsif ($n==0) { | |||
| 5612 | $date=_DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0); | |||
| 5613 | } | |||
| 5614 | ($y,$m,$d)=_Date_Split($date, 1); | |||
| 5615 | ($y,$m,$d); | |||
| 5616 | } | |||
| 5617 | ||||
| 5618 | ######################################################################## | |||
| 5619 | # LANGUAGE INITIALIZATION | |||
| 5620 | ######################################################################## | |||
| 5621 | ||||
| 5622 | # 8-bit international characters can be gotten by "\xXX". I don't know | |||
| 5623 | # how to get 16-bit characters. I've got to read up on perllocale. | |||
| 5624 | sub _Char_8Bit { | |||
| 5625 | my($hash)=@_; | |||
| 5626 | ||||
| 5627 | # grave ` | |||
| 5628 | # A` 00c0 a` 00e0 | |||
| 5629 | # E` 00c8 e` 00e8 | |||
| 5630 | # I` 00cc i` 00ec | |||
| 5631 | # O` 00d2 o` 00f2 | |||
| 5632 | # U` 00d9 u` 00f9 | |||
| 5633 | # W` 1e80 w` 1e81 | |||
| 5634 | # Y` 1ef2 y` 1ef3 | |||
| 5635 | ||||
| 5636 | $$hash{"A`"} = "\xc0"; # LATIN CAPITAL LETTER A WITH GRAVE | |||
| 5637 | $$hash{"E`"} = "\xc8"; # LATIN CAPITAL LETTER E WITH GRAVE | |||
| 5638 | $$hash{"I`"} = "\xcc"; # LATIN CAPITAL LETTER I WITH GRAVE | |||
| 5639 | $$hash{"O`"} = "\xd2"; # LATIN CAPITAL LETTER O WITH GRAVE | |||
| 5640 | $$hash{"U`"} = "\xd9"; # LATIN CAPITAL LETTER U WITH GRAVE | |||
| 5641 | $$hash{"a`"} = "\xe0"; # LATIN SMALL LETTER A WITH GRAVE | |||
| 5642 | $$hash{"e`"} = "\xe8"; # LATIN SMALL LETTER E WITH GRAVE | |||
| 5643 | $$hash{"i`"} = "\xec"; # LATIN SMALL LETTER I WITH GRAVE | |||
| 5644 | $$hash{"o`"} = "\xf2"; # LATIN SMALL LETTER O WITH GRAVE | |||
| 5645 | $$hash{"u`"} = "\xf9"; # LATIN SMALL LETTER U WITH GRAVE | |||
| 5646 | ||||
| 5647 | # acute ' | |||
| 5648 | # A' 00c1 a' 00e1 | |||
| 5649 | # C' 0106 c' 0107 | |||
| 5650 | # E' 00c9 e' 00e9 | |||
| 5651 | # I' 00cd i' 00ed | |||
| 5652 | # L' 0139 l' 013a | |||
| 5653 | # N' 0143 n' 0144 | |||
| 5654 | # O' 00d3 o' 00f3 | |||
| 5655 | # R' 0154 r' 0155 | |||
| 5656 | # S' 015a s' 015b | |||
| 5657 | # U' 00da u' 00fa | |||
| 5658 | # W' 1e82 w' 1e83 | |||
| 5659 | # Y' 00dd y' 00fd | |||
| 5660 | # Z' 0179 z' 017a | |||
| 5661 | ||||
| 5662 | $$hash{"A'"} = "\xc1"; # LATIN CAPITAL LETTER A WITH ACUTE | |||
| 5663 | $$hash{"E'"} = "\xc9"; # LATIN CAPITAL LETTER E WITH ACUTE | |||
| 5664 | $$hash{"I'"} = "\xcd"; # LATIN CAPITAL LETTER I WITH ACUTE | |||
| 5665 | $$hash{"O'"} = "\xd3"; # LATIN CAPITAL LETTER O WITH ACUTE | |||
| 5666 | $$hash{"U'"} = "\xda"; # LATIN CAPITAL LETTER U WITH ACUTE | |||
| 5667 | $$hash{"Y'"} = "\xdd"; # LATIN CAPITAL LETTER Y WITH ACUTE | |||
| 5668 | $$hash{"a'"} = "\xe1"; # LATIN SMALL LETTER A WITH ACUTE | |||
| 5669 | $$hash{"e'"} = "\xe9"; # LATIN SMALL LETTER E WITH ACUTE | |||
| 5670 | $$hash{"i'"} = "\xed"; # LATIN SMALL LETTER I WITH ACUTE | |||
| 5671 | $$hash{"o'"} = "\xf3"; # LATIN SMALL LETTER O WITH ACUTE | |||
| 5672 | $$hash{"u'"} = "\xfa"; # LATIN SMALL LETTER U WITH ACUTE | |||
| 5673 | $$hash{"y'"} = "\xfd"; # LATIN SMALL LETTER Y WITH ACUTE | |||
| 5674 | ||||
| 5675 | # double acute " " | |||
| 5676 | # O" 0150 o" 0151 | |||
| 5677 | # U" 0170 u" 0171 | |||
| 5678 | ||||
| 5679 | # circumflex ^ | |||
| 5680 | # A^ 00c2 a^ 00e2 | |||
| 5681 | # C^ 0108 c^ 0109 | |||
| 5682 | # E^ 00ca e^ 00ea | |||
| 5683 | # G^ 011c g^ 011d | |||
| 5684 | # H^ 0124 h^ 0125 | |||
| 5685 | # I^ 00ce i^ 00ee | |||
| 5686 | # J^ 0134 j^ 0135 | |||
| 5687 | # O^ 00d4 o^ 00f4 | |||
| 5688 | # S^ 015c s^ 015d | |||
| 5689 | # U^ 00db u^ 00fb | |||
| 5690 | # W^ 0174 w^ 0175 | |||
| 5691 | # Y^ 0176 y^ 0177 | |||
| 5692 | ||||
| 5693 | $$hash{"A^"} = "\xc2"; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX | |||
| 5694 | $$hash{"E^"} = "\xca"; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX | |||
| 5695 | $$hash{"I^"} = "\xce"; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX | |||
| 5696 | $$hash{"O^"} = "\xd4"; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX | |||
| 5697 | $$hash{"U^"} = "\xdb"; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX | |||
| 5698 | $$hash{"a^"} = "\xe2"; # LATIN SMALL LETTER A WITH CIRCUMFLEX | |||
| 5699 | $$hash{"e^"} = "\xea"; # LATIN SMALL LETTER E WITH CIRCUMFLEX | |||
| 5700 | $$hash{"i^"} = "\xee"; # LATIN SMALL LETTER I WITH CIRCUMFLEX | |||
| 5701 | $$hash{"o^"} = "\xf4"; # LATIN SMALL LETTER O WITH CIRCUMFLEX | |||
| 5702 | $$hash{"u^"} = "\xfb"; # LATIN SMALL LETTER U WITH CIRCUMFLEX | |||
| 5703 | ||||
| 5704 | # tilde ~ | |||
| 5705 | # A~ 00c3 a~ 00e3 | |||
| 5706 | # I~ 0128 i~ 0129 | |||
| 5707 | # N~ 00d1 n~ 00f1 | |||
| 5708 | # O~ 00d5 o~ 00f5 | |||
| 5709 | # U~ 0168 u~ 0169 | |||
| 5710 | ||||
| 5711 | $$hash{"A~"} = "\xc3"; # LATIN CAPITAL LETTER A WITH TILDE | |||
| 5712 | $$hash{"N~"} = "\xd1"; # LATIN CAPITAL LETTER N WITH TILDE | |||
| 5713 | $$hash{"O~"} = "\xd5"; # LATIN CAPITAL LETTER O WITH TILDE | |||
| 5714 | $$hash{"a~"} = "\xe3"; # LATIN SMALL LETTER A WITH TILDE | |||
| 5715 | $$hash{"n~"} = "\xf1"; # LATIN SMALL LETTER N WITH TILDE | |||
| 5716 | $$hash{"o~"} = "\xf5"; # LATIN SMALL LETTER O WITH TILDE | |||
| 5717 | ||||
| 5718 | # macron - | |||
| 5719 | # A- 0100 a- 0101 | |||
| 5720 | # E- 0112 e- 0113 | |||
| 5721 | # I- 012a i- 012b | |||
| 5722 | # O- 014c o- 014d | |||
| 5723 | # U- 016a u- 016b | |||
| 5724 | ||||
| 5725 | # breve ( [half circle up] | |||
| 5726 | # A( 0102 a( 0103 | |||
| 5727 | # G( 011e g( 011f | |||
| 5728 | # U( 016c u( 016d | |||
| 5729 | ||||
| 5730 | # dot . | |||
| 5731 | # C. 010a c. 010b | |||
| 5732 | # E. 0116 e. 0117 | |||
| 5733 | # G. 0120 g. 0121 | |||
| 5734 | # I. 0130 | |||
| 5735 | # Z. 017b z. 017c | |||
| 5736 | ||||
| 5737 | # diaeresis : [side by side dots] | |||
| 5738 | # A: 00c4 a: 00e4 | |||
| 5739 | # E: 00cb e: 00eb | |||
| 5740 | # I: 00cf i: 00ef | |||
| 5741 | # O: 00d6 o: 00f6 | |||
| 5742 | # U: 00dc u: 00fc | |||
| 5743 | # W: 1e84 w: 1e85 | |||
| 5744 | # Y: 0178 y: 00ff | |||
| 5745 | ||||
| 5746 | $$hash{"A:"} = "\xc4"; # LATIN CAPITAL LETTER A WITH DIAERESIS | |||
| 5747 | $$hash{"E:"} = "\xcb"; # LATIN CAPITAL LETTER E WITH DIAERESIS | |||
| 5748 | $$hash{"I:"} = "\xcf"; # LATIN CAPITAL LETTER I WITH DIAERESIS | |||
| 5749 | $$hash{"O:"} = "\xd6"; # LATIN CAPITAL LETTER O WITH DIAERESIS | |||
| 5750 | $$hash{"U:"} = "\xdc"; # LATIN CAPITAL LETTER U WITH DIAERESIS | |||
| 5751 | $$hash{"a:"} = "\xe4"; # LATIN SMALL LETTER A WITH DIAERESIS | |||
| 5752 | $$hash{"e:"} = "\xeb"; # LATIN SMALL LETTER E WITH DIAERESIS | |||
| 5753 | $$hash{"i:"} = "\xef"; # LATIN SMALL LETTER I WITH DIAERESIS | |||
| 5754 | $$hash{"o:"} = "\xf6"; # LATIN SMALL LETTER O WITH DIAERESIS | |||
| 5755 | $$hash{"u:"} = "\xfc"; # LATIN SMALL LETTER U WITH DIAERESIS | |||
| 5756 | $$hash{"y:"} = "\xff"; # LATIN SMALL LETTER Y WITH DIAERESIS | |||
| 5757 | ||||
| 5758 | # ring o | |||
| 5759 | # U0 016e u0 016f | |||
| 5760 | ||||
| 5761 | # cedilla , [squiggle down and left below the letter] | |||
| 5762 | # ,C 00c7 ,c 00e7 | |||
| 5763 | # ,G 0122 ,g 0123 | |||
| 5764 | # ,K 0136 ,k 0137 | |||
| 5765 | # ,L 013b ,l 013c | |||
| 5766 | # ,N 0145 ,n 0146 | |||
| 5767 | # ,R 0156 ,r 0157 | |||
| 5768 | # ,S 015e ,s 015f | |||
| 5769 | # ,T 0162 ,t 0163 | |||
| 5770 | ||||
| 5771 | $$hash{",C"} = "\xc7"; # LATIN CAPITAL LETTER C WITH CEDILLA | |||
| 5772 | $$hash{",c"} = "\xe7"; # LATIN SMALL LETTER C WITH CEDILLA | |||
| 5773 | ||||
| 5774 | # ogonek ; [squiggle down and right below the letter] | |||
| 5775 | # A; 0104 a; 0105 | |||
| 5776 | # E; 0118 e; 0119 | |||
| 5777 | # I; 012e i; 012f | |||
| 5778 | # U; 0172 u; 0173 | |||
| 5779 | ||||
| 5780 | # caron < [little v on top] | |||
| 5781 | # A< 01cd a< 01ce | |||
| 5782 | # C< 010c c< 010d | |||
| 5783 | # D< 010e d< 010f | |||
| 5784 | # E< 011a e< 011b | |||
| 5785 | # L< 013d l< 013e | |||
| 5786 | # N< 0147 n< 0148 | |||
| 5787 | # R< 0158 r< 0159 | |||
| 5788 | # S< 0160 s< 0161 | |||
| 5789 | # T< 0164 t< 0165 | |||
| 5790 | # Z< 017d z< 017e | |||
| 5791 | ||||
| 5792 | ||||
| 5793 | # Other characters | |||
| 5794 | ||||
| 5795 | # First character is below, 2nd character is above | |||
| 5796 | $$hash{"||"} = "\xa6"; # BROKEN BAR | |||
| 5797 | $$hash{" :"} = "\xa8"; # DIAERESIS | |||
| 5798 | $$hash{"-a"} = "\xaa"; # FEMININE ORDINAL INDICATOR | |||
| 5799 | #$$hash{" -"}= "\xaf"; # MACRON (narrow bar) | |||
| 5800 | $$hash{" -"} = "\xad"; # HYPHEN (wide bar) | |||
| 5801 | $$hash{" o"} = "\xb0"; # DEGREE SIGN | |||
| 5802 | $$hash{"-+"} = "\xb1"; # PLUS\342\200\220MINUS SIGN | |||
| 5803 | $$hash{" 1"} = "\xb9"; # SUPERSCRIPT ONE | |||
| 5804 | $$hash{" 2"} = "\xb2"; # SUPERSCRIPT TWO | |||
| 5805 | $$hash{" 3"} = "\xb3"; # SUPERSCRIPT THREE | |||
| 5806 | $$hash{" '"} = "\xb4"; # ACUTE ACCENT | |||
| 5807 | $$hash{"-o"} = "\xba"; # MASCULINE ORDINAL INDICATOR | |||
| 5808 | $$hash{" ."} = "\xb7"; # MIDDLE DOT | |||
| 5809 | $$hash{", "} = "\xb8"; # CEDILLA | |||
| 5810 | $$hash{"Ao"} = "\xc5"; # LATIN CAPITAL LETTER A WITH RING ABOVE | |||
| 5811 | $$hash{"ao"} = "\xe5"; # LATIN SMALL LETTER A WITH RING ABOVE | |||
| 5812 | $$hash{"ox"} = "\xf0"; # LATIN SMALL LETTER ETH | |||
| 5813 | ||||
| 5814 | # upside down characters | |||
| 5815 | ||||
| 5816 | $$hash{"ud!"} = "\xa1"; # INVERTED EXCLAMATION MARK | |||
| 5817 | $$hash{"ud?"} = "\xbf"; # INVERTED QUESTION MARK | |||
| 5818 | ||||
| 5819 | # overlay characters | |||
| 5820 | ||||
| 5821 | $$hash{"X o"} = "\xa4"; # CURRENCY SIGN | |||
| 5822 | $$hash{"Y ="} = "\xa5"; # YEN SIGN | |||
| 5823 | $$hash{"S o"} = "\xa7"; # SECTION SIGN | |||
| 5824 | $$hash{"O c"} = "\xa9"; # COPYRIGHT SIGN Copyright | |||
| 5825 | $$hash{"O R"} = "\xae"; # REGISTERED SIGN | |||
| 5826 | $$hash{"D -"} = "\xd0"; # LATIN CAPITAL LETTER ETH | |||
| 5827 | $$hash{"O /"} = "\xd8"; # LATIN CAPITAL LETTER O WITH STROKE | |||
| 5828 | $$hash{"o /"} = "\xf8"; # LATIN SMALL LETTER O WITH STROKE | |||
| 5829 | ||||
| 5830 | # special names | |||
| 5831 | ||||
| 5832 | $$hash{"1/4"} = "\xbc"; # VULGAR FRACTION ONE QUARTER | |||
| 5833 | $$hash{"1/2"} = "\xbd"; # VULGAR FRACTION ONE HALF | |||
| 5834 | $$hash{"3/4"} = "\xbe"; # VULGAR FRACTION THREE QUARTERS | |||
| 5835 | $$hash{"<<"} = "\xab"; # LEFT POINTING DOUBLE ANGLE QUOTATION MARK | |||
| 5836 | $$hash{">>"} = "\xbb"; # RIGHT POINTING DOUBLE ANGLE QUOTATION MARK | |||
| 5837 | $$hash{"cent"}= "\xa2"; # CENT SIGN | |||
| 5838 | $$hash{"lb"} = "\xa3"; # POUND SIGN | |||
| 5839 | $$hash{"mu"} = "\xb5"; # MICRO SIGN | |||
| 5840 | $$hash{"beta"}= "\xdf"; # LATIN SMALL LETTER SHARP S | |||
| 5841 | $$hash{"para"}= "\xb6"; # PILCROW SIGN | |||
| 5842 | $$hash{"-|"} = "\xac"; # NOT SIGN | |||
| 5843 | $$hash{"AE"} = "\xc6"; # LATIN CAPITAL LETTER AE | |||
| 5844 | $$hash{"ae"} = "\xe6"; # LATIN SMALL LETTER AE | |||
| 5845 | $$hash{"x"} = "\xd7"; # MULTIPLICATION SIGN | |||
| 5846 | $$hash{"P"} = "\xde"; # LATIN CAPITAL LETTER THORN | |||
| 5847 | $$hash{"/"} = "\xf7"; # DIVISION SIGN | |||
| 5848 | $$hash{"p"} = "\xfe"; # LATIN SMALL LETTER THORN | |||
| 5849 | } | |||
| 5850 | ||||
| 5851 | # $hashref = _Date_Init_LANGUAGE; | |||
| 5852 | # This returns a hash containing all of the initialization for a | |||
| 5853 | # specific language. The hash elements are: | |||
| 5854 | # | |||
| 5855 | # @ month_name full month names January February ... | |||
| 5856 | # @ month_abb month abbreviations Jan Feb ... | |||
| 5857 | # @ day_name day names Monday Tuesday ... | |||
| 5858 | # @ day_abb day abbreviations Mon Tue ... | |||
| 5859 | # @ day_char day character abbrevs M T ... | |||
| 5860 | # @ am AM notations | |||
| 5861 | # @ pm PM notations | |||
| 5862 | # | |||
| 5863 | # @ num_suff number with suffix 1st 2nd ... | |||
| 5864 | # @ num_word numbers spelled out first second ... | |||
| 5865 | # | |||
| 5866 | # $ now words which mean now now ... | |||
| 5867 | # $ today words which mean today today ... | |||
| 5868 | # $ last words which mean last last final ... | |||
| 5869 | # $ each words which mean each each every ... | |||
| 5870 | # $ of of (as in a member of) in of ... | |||
| 5871 | # ex. 4th day OF June | |||
| 5872 | # $ at at 4:00 at | |||
| 5873 | # $ on on Sunday on | |||
| 5874 | # $ future in the future in | |||
| 5875 | # $ past in the past ago | |||
| 5876 | # $ next next item next | |||
| 5877 | # $ prev previous item last previous | |||
| 5878 | # $ later 2 hours later | |||
| 5879 | # | |||
| 5880 | # % offset a hash of special dates { tomorrow->0:0:0:1:0:0:0 } | |||
| 5881 | # % times a hash of times { noon->12:00:00 ... } | |||
| 5882 | # | |||
| 5883 | # $ years words for year y yr year ... | |||
| 5884 | # $ months words for month | |||
| 5885 | # $ weeks words for week | |||
| 5886 | # $ days words for day | |||
| 5887 | # $ hours words for hour | |||
| 5888 | # $ minutes words for minute | |||
| 5889 | # $ seconds words for second | |||
| 5890 | # % replace | |||
| 5891 | # The replace element is quite important, but a bit tricky. In | |||
| 5892 | # English (and probably other languages), one of the abbreviations | |||
| 5893 | # for the word month that would be nice is "m". The problem is that | |||
| 5894 | # "m" matches the "m" in "minute" which causes the string to be | |||
| 5895 | # improperly matched in some cases. Hence, the list of abbreviations | |||
| 5896 | # for month is given as: | |||
| 5897 | # "mon month months" | |||
| 5898 | # In order to allow you to enter "m", replacements can be done. | |||
| 5899 | # $replace is a list of pairs of words which are matched and replaced | |||
| 5900 | # AS ENTIRE WORDS. Having $replace equal to "m"->"month" means that | |||
| 5901 | # the entire word "m" will be replaced with "month". This allows the | |||
| 5902 | # desired abbreviation to be used. Make sure that replace contains | |||
| 5903 | # an even number of words (i.e. all must be pairs). Any time a | |||
| 5904 | # desired abbreviation matches the start of any other, it has to go | |||
| 5905 | # here. | |||
| 5906 | # | |||
| 5907 | # $ exact exact mode exactly | |||
| 5908 | # $ approx approximate mode approximately | |||
| 5909 | # $ business business mode business | |||
| 5910 | # | |||
| 5911 | # r sephm hour/minute separator (?::) | |||
| 5912 | # r sepms minute/second separator (?::) | |||
| 5913 | # r sepss second/fraction separator (?:[.:]) | |||
| 5914 | # | |||
| 5915 | # Elements marked with an asterix (@) are returned as a set of lists. | |||
| 5916 | # Each list contains the strings for each element. The first set is used | |||
| 5917 | # when the 7-bit ASCII (US) character set is wanted. The 2nd set is used | |||
| 5918 | # when an international character set is available. Both of the 1st two | |||
| 5919 | # sets should be complete (but the 2nd list can be left empty to force the | |||
| 5920 | # first set to be used always). The 3rd set and later can be partial sets | |||
| 5921 | # if desired. | |||
| 5922 | # | |||
| 5923 | # Elements marked with a dollar ($) are returned as a simple list of words. | |||
| 5924 | # | |||
| 5925 | # Elements marked with a percent (%) are returned as a hash list. | |||
| 5926 | # | |||
| 5927 | # Elements marked with (r) are regular expression elements which must not | |||
| 5928 | # create a back reference. | |||
| 5929 | # | |||
| 5930 | # ***NOTE*** Every hash element (unless otherwise noted) MUST be defined in | |||
| 5931 | # every language. | |||
| 5932 | ||||
| 5933 | sub _Date_Init_English { | |||
| 5934 | print "DEBUG: _Date_Init_English\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 5935 | my($d)=@_; | |||
| 5936 | ||||
| 5937 | $$d{"month_name"}= | |||
| 5938 | [["January","February","March","April","May","June", | |||
| 5939 | "July","August","September","October","November","December"]]; | |||
| 5940 | ||||
| 5941 | $$d{"month_abb"}= | |||
| 5942 | [["Jan","Feb","Mar","Apr","May","Jun", | |||
| 5943 | "Jul","Aug","Sep","Oct","Nov","Dec"], | |||
| 5944 | [], | |||
| 5945 | ["","","","","","","","","Sept"]]; | |||
| 5946 | ||||
| 5947 | $$d{"day_name"}= | |||
| 5948 | [["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]]; | |||
| 5949 | $$d{"day_abb"}= | |||
| 5950 | [["Mon","Tue","Wed","Thu","Fri","Sat","Sun"], | |||
| 5951 | ["", "Tues","", "Thur","", "", ""]]; | |||
| 5952 | $$d{"day_char"}= | |||
| 5953 | [["M","T","W","Th","F","Sa","S"]]; | |||
| 5954 | ||||
| 5955 | $$d{"num_suff"}= | |||
| 5956 | [["1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th", | |||
| 5957 | "11th","12th","13th","14th","15th","16th","17th","18th","19th","20th", | |||
| 5958 | "21st","22nd","23rd","24th","25th","26th","27th","28th","29th","30th", | |||
| 5959 | "31st"]]; | |||
| 5960 | $$d{"num_word"}= | |||
| 5961 | [["first","second","third","fourth","fifth","sixth","seventh","eighth", | |||
| 5962 | "ninth","tenth","eleventh","twelfth","thirteenth","fourteenth", | |||
| 5963 | "fifteenth","sixteenth","seventeenth","eighteenth","nineteenth", | |||
| 5964 | "twentieth","twenty-first","twenty-second","twenty-third", | |||
| 5965 | "twenty-fourth","twenty-fifth","twenty-sixth","twenty-seventh", | |||
| 5966 | "twenty-eighth","twenty-ninth","thirtieth","thirty-first"]]; | |||
| 5967 | ||||
| 5968 | $$d{"now"} =["now"]; | |||
| 5969 | $$d{"today"} =["today"]; | |||
| 5970 | $$d{"last"} =["last","final"]; | |||
| 5971 | $$d{"each"} =["each","every"]; | |||
| 5972 | $$d{"of"} =["in","of"]; | |||
| 5973 | $$d{"at"} =["at"]; | |||
| 5974 | $$d{"on"} =["on"]; | |||
| 5975 | $$d{"future"} =["in"]; | |||
| 5976 | $$d{"past"} =["ago"]; | |||
| 5977 | $$d{"next"} =["next"]; | |||
| 5978 | $$d{"prev"} =["previous","last"]; | |||
| 5979 | $$d{"later"} =["later"]; | |||
| 5980 | ||||
| 5981 | $$d{"exact"} =["exactly"]; | |||
| 5982 | $$d{"approx"} =["approximately"]; | |||
| 5983 | $$d{"business"}=["business"]; | |||
| 5984 | ||||
| 5985 | $$d{"offset"} =["yesterday","-0:0:0:1:0:0:0","tomorrow","+0:0:0:1:0:0:0","overmorrow","+0:0:0:2:0:0:0","ereyesterday","-0:0:0:2:0:0:0"]; | |||
| 5986 | $$d{"times"} =["noon","12:00:00","midnight","00:00:00"]; | |||
| 5987 | ||||
| 5988 | $$d{"years"} =["y","yr","year","yrs","years"]; | |||
| 5989 | $$d{"months"} =["mon","month","months"]; | |||
| 5990 | $$d{"weeks"} =["w","wk","wks","week","weeks"]; | |||
| 5991 | $$d{"days"} =["d","day","days"]; | |||
| 5992 | $$d{"hours"} =["h","hr","hrs","hour","hours"]; | |||
| 5993 | $$d{"minutes"} =["mn","min","minute","minutes"]; | |||
| 5994 | $$d{"seconds"} =["s","sec","second","seconds"]; | |||
| 5995 | $$d{"replace"} =["m","month"]; | |||
| 5996 | ||||
| 5997 | $$d{"sephm"} =':'; | |||
| 5998 | $$d{"sepms"} =':'; | |||
| 5999 | $$d{"sepss"} ='[.:]'; | |||
| 6000 | ||||
| 6001 | $$d{"am"} = ["AM","A.M."]; | |||
| 6002 | $$d{"pm"} = ["PM","P.M."]; | |||
| 6003 | } | |||
| 6004 | ||||
| 6005 | sub _Date_Init_Italian { | |||
| 6006 | print "DEBUG: _Date_Init_Italian\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6007 | my($d)=@_; | |||
| 6008 | my(%h)=(); | |||
| 6009 | _Char_8Bit(\%h); | |||
| 6010 | my($i)=$h{"i`"}; | |||
| 6011 | ||||
| 6012 | $$d{"month_name"}= | |||
| 6013 | [[qw(Gennaio Febbraio Marzo Aprile Maggio Giugno | |||
| 6014 | Luglio Agosto Settembre Ottobre Novembre Dicembre)]]; | |||
| 6015 | ||||
| 6016 | $$d{"month_abb"}= | |||
| 6017 | [[qw(Gen Feb Mar Apr Mag Giu Lug Ago Set Ott Nov Dic)]]; | |||
| 6018 | ||||
| 6019 | $$d{"day_name"}= | |||
| 6020 | [[qw(Lunedi Martedi Mercoledi Giovedi Venerdi Sabato Domenica)], | |||
| 6021 | [qw(Luned${i} Marted${i} Mercoled${i} Gioved${i} Venerd${i})]]; | |||
| 6022 | $$d{"day_abb"}= | |||
| 6023 | [[qw(Lun Mar Mer Gio Ven Sab Dom)]]; | |||
| 6024 | $$d{"day_char"}= | |||
| 6025 | [[qw(L Ma Me G V S D)]]; | |||
| 6026 | ||||
| 6027 | $$d{"num_suff"}= | |||
| 6028 | [[qw(1mo 2do 3zo 4to 5to 6to 7mo 8vo 9no 10mo 11mo 12mo 13mo 14mo 15mo | |||
| 6029 | 16mo 17mo 18mo 19mo 20mo 21mo 22mo 23mo 24mo 25mo 26mo 27mo 28mo | |||
| 6030 | 29mo 3mo 31mo)]]; | |||
| 6031 | $$d{"num_word"}= | |||
| 6032 | [[qw(primo secondo terzo quarto quinto sesto settimo ottavo nono decimo | |||
| 6033 | undicesimo dodicesimo tredicesimo quattordicesimo quindicesimo | |||
| 6034 | sedicesimo diciassettesimo diciottesimo diciannovesimo ventesimo | |||
| 6035 | ventunesimo ventiduesimo ventitreesimo ventiquattresimo | |||
| 6036 | venticinquesimo ventiseiesimo ventisettesimo ventottesimo | |||
| 6037 | ventinovesimo trentesimo trentunesimo)]]; | |||
| 6038 | ||||
| 6039 | $$d{"now"} =[qw(adesso)]; | |||
| 6040 | $$d{"today"} =[qw(oggi)]; | |||
| 6041 | $$d{"last"} =[qw(ultimo)]; | |||
| 6042 | $$d{"each"} =[qw(ogni)]; | |||
| 6043 | $$d{"of"} =[qw(della del)]; | |||
| 6044 | $$d{"at"} =[qw(alle)]; | |||
| 6045 | $$d{"on"} =[qw(di)]; | |||
| 6046 | $$d{"future"} =[qw(fra)]; | |||
| 6047 | $$d{"past"} =[qw(fa)]; | |||
| 6048 | $$d{"next"} =[qw(prossimo)]; | |||
| 6049 | $$d{"prev"} =[qw(ultimo)]; | |||
| 6050 | $$d{"later"} =[qw(dopo)]; | |||
| 6051 | ||||
| 6052 | $$d{"exact"} =[qw(esattamente)]; | |||
| 6053 | $$d{"approx"} =[qw(circa)]; | |||
| 6054 | $$d{"business"}=[qw(lavorativi lavorativo)]; | |||
| 6055 | ||||
| 6056 | $$d{"offset"} =[qw(ieri -0:0:0:1:0:0:0 domani +0:0:0:1:0:0:0)]; | |||
| 6057 | $$d{"times"} =[qw(mezzogiorno 12:00:00 mezzanotte 00:00:00)]; | |||
| 6058 | ||||
| 6059 | $$d{"years"} =[qw(anni anno a)]; | |||
| 6060 | $$d{"months"} =[qw(mesi mese mes)]; | |||
| 6061 | $$d{"weeks"} =[qw(settimane settimana sett)]; | |||
| 6062 | $$d{"days"} =[qw(giorni giorno g)]; | |||
| 6063 | $$d{"hours"} =[qw(ore ora h)]; | |||
| 6064 | $$d{"minutes"} =[qw(minuti minuto min)]; | |||
| 6065 | $$d{"seconds"} =[qw(secondi secondo sec)]; | |||
| 6066 | $$d{"replace"} =[qw(s sec m mes)]; | |||
| 6067 | ||||
| 6068 | $$d{"sephm"} =':'; | |||
| 6069 | $$d{"sepms"} =':'; | |||
| 6070 | $$d{"sepss"} ='[.:]'; | |||
| 6071 | ||||
| 6072 | $$d{"am"} = [qw(AM)]; | |||
| 6073 | $$d{"pm"} = [qw(PM)]; | |||
| 6074 | } | |||
| 6075 | ||||
| 6076 | sub _Date_Init_French { | |||
| 6077 | print "DEBUG: _Date_Init_French\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6078 | my($d)=@_; | |||
| 6079 | my(%h)=(); | |||
| 6080 | _Char_8Bit(\%h); | |||
| 6081 | my($e)=$h{"e'"}; | |||
| 6082 | my($u)=$h{"u^"}; | |||
| 6083 | my($a)=$h{"a'"}; | |||
| 6084 | ||||
| 6085 | $$d{"month_name"}= | |||
| 6086 | [["janvier","fevrier","mars","avril","mai","juin", | |||
| 6087 | "juillet","aout","septembre","octobre","novembre","decembre"], | |||
| 6088 | ["janvier","f${e}vrier","mars","avril","mai","juin", | |||
| 6089 | "juillet","ao${u}t","septembre","octobre","novembre","d${e}cembre"]]; | |||
| 6090 | $$d{"month_abb"}= | |||
| 6091 | [["jan","fev","mar","avr","mai","juin", | |||
| 6092 | "juil","aout","sept","oct","nov","dec"], | |||
| 6093 | ["jan","f${e}v","mar","avr","mai","juin", | |||
| 6094 | "juil","ao${u}t","sept","oct","nov","d${e}c"]]; | |||
| 6095 | ||||
| 6096 | $$d{"day_name"}= | |||
| 6097 | [["lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"]]; | |||
| 6098 | $$d{"day_abb"}= | |||
| 6099 | [["lun","mar","mer","jeu","ven","sam","dim"]]; | |||
| 6100 | $$d{"day_char"}= | |||
| 6101 | [["l","ma","me","j","v","s","d"]]; | |||
| 6102 | ||||
| 6103 | $$d{"num_suff"}= | |||
| 6104 | [["1er","2e","3e","4e","5e","6e","7e","8e","9e","10e", | |||
| 6105 | "11e","12e","13e","14e","15e","16e","17e","18e","19e","20e", | |||
| 6106 | "21e","22e","23e","24e","25e","26e","27e","28e","29e","30e", | |||
| 6107 | "31e"]]; | |||
| 6108 | $$d{"num_word"}= | |||
| 6109 | [["premier","deux","trois","quatre","cinq","six","sept","huit","neuf", | |||
| 6110 | "dix","onze","douze","treize","quatorze","quinze","seize","dix-sept", | |||
| 6111 | "dix-huit","dix-neuf","vingt","vingt et un","vingt-deux","vingt-trois", | |||
| 6112 | "vingt-quatre","vingt-cinq","vingt-six","vingt-sept","vingt-huit", | |||
| 6113 | "vingt-neuf","trente","trente et un"], | |||
| 6114 | ["1re"]]; | |||
| 6115 | ||||
| 6116 | $$d{"now"} =["maintenant"]; | |||
| 6117 | $$d{"today"} =["aujourd'hui"]; | |||
| 6118 | $$d{"last"} =["dernier"]; | |||
| 6119 | $$d{"each"} =["chaque","tous les","toutes les"]; | |||
| 6120 | $$d{"of"} =["en","de"]; | |||
| 6121 | $$d{"at"} =["a","${a}0"]; | |||
| 6122 | $$d{"on"} =["sur"]; | |||
| 6123 | $$d{"future"} =["en"]; | |||
| 6124 | $$d{"past"} =["il y a"]; | |||
| 6125 | $$d{"next"} =["suivant"]; | |||
| 6126 | $$d{"prev"} =["precedent","pr${e}c${e}dent"]; | |||
| 6127 | $$d{"later"} =["plus tard"]; | |||
| 6128 | ||||
| 6129 | $$d{"exact"} =["exactement"]; | |||
| 6130 | $$d{"approx"} =["approximativement"]; | |||
| 6131 | $$d{"business"}=["professionel"]; | |||
| 6132 | ||||
| 6133 | $$d{"offset"} =["hier","-0:0:0:1:0:0:0","demain","+0:0:0:1:0:0:0"]; | |||
| 6134 | $$d{"times"} =["midi","12:00:00","minuit","00:00:00"]; | |||
| 6135 | ||||
| 6136 | $$d{"years"} =["an","annee","ans","annees","ann${e}e","ann${e}es"]; | |||
| 6137 | $$d{"months"} =["mois"]; | |||
| 6138 | $$d{"weeks"} =["sem","semaine"]; | |||
| 6139 | $$d{"days"} =["j","jour","jours"]; | |||
| 6140 | $$d{"hours"} =["h","heure","heures"]; | |||
| 6141 | $$d{"minutes"} =["mn","min","minute","minutes"]; | |||
| 6142 | $$d{"seconds"} =["s","sec","seconde","secondes"]; | |||
| 6143 | $$d{"replace"} =["m","mois"]; | |||
| 6144 | ||||
| 6145 | $$d{"sephm"} ='[h:]'; | |||
| 6146 | $$d{"sepms"} =':'; | |||
| 6147 | $$d{"sepss"} ='[.:,]'; | |||
| 6148 | ||||
| 6149 | $$d{"am"} = ["du matin"]; | |||
| 6150 | $$d{"pm"} = ["du soir"]; | |||
| 6151 | } | |||
| 6152 | ||||
| 6153 | sub _Date_Init_Romanian { | |||
| 6154 | print "DEBUG: _Date_Init_Romanian\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6155 | my($d)=@_; | |||
| 6156 | my(%h)=(); | |||
| 6157 | _Char_8Bit(\%h); | |||
| 6158 | my($p)=$h{"p"}; | |||
| 6159 | my($i)=$h{"i^"}; | |||
| 6160 | my($a)=$h{"a~"}; | |||
| 6161 | my($o)=$h{"-o"}; | |||
| 6162 | ||||
| 6163 | $$d{"month_name"}= | |||
| 6164 | [["ianuarie","februarie","martie","aprilie","mai","iunie", | |||
| 6165 | "iulie","august","septembrie","octombrie","noiembrie","decembrie"]]; | |||
| 6166 | $$d{"month_abb"}= | |||
| 6167 | [["ian","febr","mart","apr","mai","iun", | |||
| 6168 | "iul","aug","sept","oct","nov","dec"], | |||
| 6169 | ["","feb"]]; | |||
| 6170 | ||||
| 6171 | $$d{"day_name"}= | |||
| 6172 | [["luni","marti","miercuri","joi","vineri","simbata","duminica"], | |||
| 6173 | ["luni","mar${p}i","miercuri","joi","vineri","s${i}mb${a}t${a}", | |||
| 6174 | "duminic${a}"]]; | |||
| 6175 | $$d{"day_abb"}= | |||
| 6176 | [["lun","mar","mie","joi","vin","sim","dum"], | |||
| 6177 | ["lun","mar","mie","joi","vin","s${i}m","dum"]]; | |||
| 6178 | $$d{"day_char"}= | |||
| 6179 | [["L","Ma","Mi","J","V","S","D"]]; | |||
| 6180 | ||||
| 6181 | $$d{"num_suff"}= | |||
| 6182 | [["prima","a doua","a 3-a","a 4-a","a 5-a","a 6-a","a 7-a","a 8-a", | |||
| 6183 | "a 9-a","a 10-a","a 11-a","a 12-a","a 13-a","a 14-a","a 15-a", | |||
| 6184 | "a 16-a","a 17-a","a 18-a","a 19-a","a 20-a","a 21-a","a 22-a", | |||
| 6185 | "a 23-a","a 24-a","a 25-a","a 26-a","a 27-a","a 28-a","a 29-a", | |||
| 6186 | "a 30-a","a 31-a"]]; | |||
| 6187 | ||||
| 6188 | $$d{"num_word"}= | |||
| 6189 | [["prima","a doua","a treia","a patra","a cincea","a sasea","a saptea", | |||
| 6190 | "a opta","a noua","a zecea","a unsprezecea","a doisprezecea", | |||
| 6191 | "a treisprezecea","a patrusprezecea","a cincisprezecea","a saiprezecea", | |||
| 6192 | "a saptesprezecea","a optsprezecea","a nouasprezecea","a douazecea", | |||
| 6193 | "a douazecisiuna","a douazecisidoua","a douazecisitreia", | |||
| 6194 | "a douazecisipatra","a douazecisicincea","a douazecisisasea", | |||
| 6195 | "a douazecisisaptea","a douazecisiopta","a douazecisinoua","a treizecea", | |||
| 6196 | "a treizecisiuna"], | |||
| 6197 | ["prima","a doua","a treia","a patra","a cincea","a ${o}asea", | |||
| 6198 | "a ${o}aptea","a opta","a noua","a zecea","a unsprezecea", | |||
| 6199 | "a doisprezecea","a treisprezecea","a patrusprezecea","a cincisprezecea", | |||
| 6200 | "a ${o}aiprezecea","a ${o}aptesprezecea","a optsprezecea", | |||
| 6201 | "a nou${a}sprezecea","a dou${a}zecea","a dou${a}zeci${o}iuna", | |||
| 6202 | "a dou${a}zeci${o}idoua","a dou${a}zeci${o}itreia", | |||
| 6203 | "a dou${a}zeci${o}ipatra","a dou${a}zeci${o}icincea", | |||
| 6204 | "a dou${a}zeci${o}i${o}asea","a dou${a}zeci${o}i${o}aptea", | |||
| 6205 | "a dou${a}zeci${o}iopta","a dou${a}zeci${o}inoua","a treizecea", | |||
| 6206 | "a treizeci${o}iuna"], | |||
| 6207 | ["intii", "doi", "trei", "patru", "cinci", "sase", "sapte", | |||
| 6208 | "opt","noua","zece","unsprezece","doisprezece", | |||
| 6209 | "treisprezece","patrusprezece","cincisprezece","saiprezece", | |||
| 6210 | "saptesprezece","optsprezece","nouasprezece","douazeci", | |||
| 6211 | "douazecisiunu","douazecisidoi","douazecisitrei", | |||
| 6212 | "douazecisipatru","douazecisicinci","douazecisisase","douazecisisapte", | |||
| 6213 | "douazecisiopt","douazecisinoua","treizeci","treizecisiunu"], | |||
| 6214 | ["${i}nt${i}i", "doi", "trei", "patru", "cinci", "${o}ase", "${o}apte", | |||
| 6215 | "opt","nou${a}","zece","unsprezece","doisprezece", | |||
| 6216 | "treisprezece","patrusprezece","cincisprezece","${o}aiprezece", | |||
| 6217 | "${o}aptesprezece","optsprezece","nou${a}sprezece","dou${a}zeci", | |||
| 6218 | "dou${a}zeci${o}iunu","dou${a}zeci${o}idoi","dou${a}zeci${o}itrei", | |||
| 6219 | "dou${a}zecisipatru","dou${a}zeci${o}icinci","dou${a}zeci${o}i${o}ase", | |||
| 6220 | "dou${a}zeci${o}i${o}apte","dou${a}zeci${o}iopt", | |||
| 6221 | "dou${a}zeci${o}inou${a}","treizeci","treizeci${o}iunu"]]; | |||
| 6222 | ||||
| 6223 | $$d{"now"} =["acum"]; | |||
| 6224 | $$d{"today"} =["azi","astazi","ast${a}zi"]; | |||
| 6225 | $$d{"last"} =["ultima"]; | |||
| 6226 | $$d{"each"} =["fiecare"]; | |||
| 6227 | $$d{"of"} =["din","in","n"]; | |||
| 6228 | $$d{"at"} =["la"]; | |||
| 6229 | $$d{"on"} =["on"]; | |||
| 6230 | $$d{"future"} =["in","${i}n"]; | |||
| 6231 | $$d{"past"} =["in urma", "${i}n urm${a}"]; | |||
| 6232 | $$d{"next"} =["urmatoarea","urm${a}toarea"]; | |||
| 6233 | $$d{"prev"} =["precedenta","ultima"]; | |||
| 6234 | $$d{"later"} =["mai tirziu", "mai t${i}rziu"]; | |||
| 6235 | ||||
| 6236 | $$d{"exact"} =["exact"]; | |||
| 6237 | $$d{"approx"} =["aproximativ"]; | |||
| 6238 | $$d{"business"}=["de lucru","lucratoare","lucr${a}toare"]; | |||
| 6239 | ||||
| 6240 | $$d{"offset"} =["ieri","-0:0:0:1:0:0:0", | |||
| 6241 | "alaltaieri", "-0:0:0:2:0:0:0", | |||
| 6242 | "alalt${a}ieri","-0:0:0:2:0:0:0", | |||
| 6243 | "miine","+0:0:0:1:0:0:0", | |||
| 6244 | "m${i}ine","+0:0:0:1:0:0:0", | |||
| 6245 | "poimiine","+0:0:0:2:0:0:0", | |||
| 6246 | "poim${i}ine","+0:0:0:2:0:0:0"]; | |||
| 6247 | $$d{"times"} =["amiaza","12:00:00", | |||
| 6248 | "amiaz${a}","12:00:00", | |||
| 6249 | "miezul noptii","00:00:00", | |||
| 6250 | "miezul nop${p}ii","00:00:00"]; | |||
| 6251 | ||||
| 6252 | $$d{"years"} =["ani","an","a"]; | |||
| 6253 | $$d{"months"} =["luni","luna","lun${a}","l"]; | |||
| 6254 | $$d{"weeks"} =["saptamini","s${a}pt${a}m${i}ni","saptamina", | |||
| 6255 | "s${a}pt${a}m${i}na","sapt","s${a}pt"]; | |||
| 6256 | $$d{"days"} =["zile","zi","z"]; | |||
| 6257 | $$d{"hours"} =["ore", "ora", "or${a}", "h"]; | |||
| 6258 | $$d{"minutes"} =["minute","min","m"]; | |||
| 6259 | $$d{"seconds"} =["secunde","sec",]; | |||
| 6260 | $$d{"replace"} =["s","secunde"]; | |||
| 6261 | ||||
| 6262 | $$d{"sephm"} =':'; | |||
| 6263 | $$d{"sepms"} =':'; | |||
| 6264 | $$d{"sepss"} ='[.:,]'; | |||
| 6265 | ||||
| 6266 | $$d{"am"} = ["AM","A.M."]; | |||
| 6267 | $$d{"pm"} = ["PM","P.M."]; | |||
| 6268 | } | |||
| 6269 | ||||
| 6270 | sub _Date_Init_Swedish { | |||
| 6271 | print "DEBUG: _Date_Init_Swedish\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6272 | my($d)=@_; | |||
| 6273 | my(%h)=(); | |||
| 6274 | _Char_8Bit(\%h); | |||
| 6275 | my($ao)=$h{"ao"}; | |||
| 6276 | my($o) =$h{"o:"}; | |||
| 6277 | my($a) =$h{"a:"}; | |||
| 6278 | ||||
| 6279 | $$d{"month_name"}= | |||
| 6280 | [["Januari","Februari","Mars","April","Maj","Juni", | |||
| 6281 | "Juli","Augusti","September","Oktober","November","December"]]; | |||
| 6282 | $$d{"month_abb"}= | |||
| 6283 | [["Jan","Feb","Mar","Apr","Maj","Jun", | |||
| 6284 | "Jul","Aug","Sep","Okt","Nov","Dec"]]; | |||
| 6285 | ||||
| 6286 | $$d{"day_name"}= | |||
| 6287 | [["Mandag","Tisdag","Onsdag","Torsdag","Fredag","Lordag","Sondag"], | |||
| 6288 | ["M${ao}ndag","Tisdag","Onsdag","Torsdag","Fredag","L${o}rdag", | |||
| 6289 | "S${o}ndag"]]; | |||
| 6290 | $$d{"day_abb"}= | |||
| 6291 | [["Man","Tis","Ons","Tor","Fre","Lor","Son"], | |||
| 6292 | ["M${ao}n","Tis","Ons","Tor","Fre","L${o}r","S${o}n"]]; | |||
| 6293 | $$d{"day_char"}= | |||
| 6294 | [["M","Ti","O","To","F","L","S"]]; | |||
| 6295 | ||||
| 6296 | $$d{"num_suff"}= | |||
| 6297 | [["1:a","2:a","3:e","4:e","5:e","6:e","7:e","8:e","9:e","10:e", | |||
| 6298 | "11:e","12:e","13:e","14:e","15:e","16:e","17:e","18:e","19:e","20:e", | |||
| 6299 | "21:a","22:a","23:e","24:e","25:e","26:e","27:e","28:e","29:e","30:e", | |||
| 6300 | "31:a"]]; | |||
| 6301 | $$d{"num_word"}= | |||
| 6302 | [["forsta","andra","tredje","fjarde","femte","sjatte","sjunde", | |||
| 6303 | "attonde","nionde","tionde","elfte","tolfte","trettonde","fjortonde", | |||
| 6304 | "femtonde","sextonde","sjuttonde","artonde","nittonde","tjugonde", | |||
| 6305 | "tjugoforsta","tjugoandra","tjugotredje","tjugofjarde","tjugofemte", | |||
| 6306 | "tjugosjatte","tjugosjunde","tjugoattonde","tjugonionde", | |||
| 6307 | "trettionde","trettioforsta"], | |||
| 6308 | ["f${o}rsta","andra","tredje","fj${a}rde","femte","sj${a}tte","sjunde", | |||
| 6309 | "${ao}ttonde","nionde","tionde","elfte","tolfte","trettonde","fjortonde", | |||
| 6310 | "femtonde","sextonde","sjuttonde","artonde","nittonde","tjugonde", | |||
| 6311 | "tjugof${o}rsta","tjugoandra","tjugotredje","tjugofj${a}rde","tjugofemte", | |||
| 6312 | "tjugosj${a}tte","tjugosjunde","tjugo${ao}ttonde","tjugonionde", | |||
| 6313 | "trettionde","trettiof${o}rsta"]]; | |||
| 6314 | ||||
| 6315 | $$d{"now"} =["nu"]; | |||
| 6316 | $$d{"today"} =["idag"]; | |||
| 6317 | $$d{"last"} =["forra","f${o}rra","senaste"]; | |||
| 6318 | $$d{"each"} =["varje"]; | |||
| 6319 | $$d{"of"} =["om"]; | |||
| 6320 | $$d{"at"} =["kl","kl.","klockan"]; | |||
| 6321 | $$d{"on"} =["pa","p${ao}"]; | |||
| 6322 | $$d{"future"} =["om"]; | |||
| 6323 | $$d{"past"} =["sedan"]; | |||
| 6324 | $$d{"next"} =["nasta","n${a}sta"]; | |||
| 6325 | $$d{"prev"} =["forra","f${o}rra"]; | |||
| 6326 | $$d{"later"} =["senare"]; | |||
| 6327 | ||||
| 6328 | $$d{"exact"} =["exakt"]; | |||
| 6329 | $$d{"approx"} =["ungefar","ungef${a}r"]; | |||
| 6330 | $$d{"business"}=["arbetsdag","arbetsdagar"]; | |||
| 6331 | ||||
| 6332 | $$d{"offset"} =["ig${ao}r","-0:0:0:1:0:0:0","igar","-0:0:0:1:0:0:0", | |||
| 6333 | "imorgon","+0:0:0:1:0:0:0"]; | |||
| 6334 | $$d{"times"} =["mitt pa dagen","12:00:00","mitt p${ao} dagen","12:00:00", | |||
| 6335 | "midnatt","00:00:00"]; | |||
| 6336 | ||||
| 6337 | $$d{"years"} =["ar","${ao}r"]; | |||
| 6338 | $$d{"months"} =["man","manad","manader","m${ao}n","m${ao}nad","m${ao}nader"]; | |||
| 6339 | $$d{"weeks"} =["v","vecka","veckor"]; | |||
| 6340 | $$d{"days"} =["d","dag","dagar"]; | |||
| 6341 | $$d{"hours"} =["t","tim","timme","timmar"]; | |||
| 6342 | $$d{"minutes"} =["min","minut","minuter"]; | |||
| 6343 | $$d{"seconds"} =["s","sek","sekund","sekunder"]; | |||
| 6344 | $$d{"replace"} =["m","minut"]; | |||
| 6345 | ||||
| 6346 | $$d{"sephm"} ='[.:]'; | |||
| 6347 | $$d{"sepms"} =':'; | |||
| 6348 | $$d{"sepss"} ='[.:]'; | |||
| 6349 | ||||
| 6350 | $$d{"am"} = ["FM"]; | |||
| 6351 | $$d{"pm"} = ["EM"]; | |||
| 6352 | } | |||
| 6353 | ||||
| 6354 | sub _Date_Init_German { | |||
| 6355 | print "DEBUG: _Date_Init_German\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6356 | my($d)=@_; | |||
| 6357 | my(%h)=(); | |||
| 6358 | _Char_8Bit(\%h); | |||
| 6359 | my($a)=$h{"a:"}; | |||
| 6360 | my($u)=$h{"u:"}; | |||
| 6361 | my($o)=$h{"o:"}; | |||
| 6362 | my($b)=$h{"beta"}; | |||
| 6363 | ||||
| 6364 | $$d{"month_name"}= | |||
| 6365 | [["Januar","Februar","Maerz","April","Mai","Juni", | |||
| 6366 | "Juli","August","September","Oktober","November","Dezember"], | |||
| 6367 | ["J${a}nner","Februar","M${a}rz","April","Mai","Juni", | |||
| 6368 | "Juli","August","September","Oktober","November","Dezember"]]; | |||
| 6369 | $$d{"month_abb"}= | |||
| 6370 | [["Jan","Feb","Mar","Apr","Mai","Jun", | |||
| 6371 | "Jul","Aug","Sep","Okt","Nov","Dez"], | |||
| 6372 | ["J${a}n","Feb","M${a}r","Apr","Mai","Jun", | |||
| 6373 | "Jul","Aug","Sep","Okt","Nov","Dez"]]; | |||
| 6374 | ||||
| 6375 | $$d{"day_name"}= | |||
| 6376 | [["Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag", | |||
| 6377 | "Sonntag"]]; | |||
| 6378 | $$d{"day_abb"}= | |||
| 6379 | [["Mo","Di","Mi","Do","Fr","Sa","So"]]; | |||
| 6380 | $$d{"day_char"}= | |||
| 6381 | [["M","Di","Mi","Do","F","Sa","So"]]; | |||
| 6382 | ||||
| 6383 | $$d{"num_suff"}= | |||
| 6384 | [["1.","2.","3.","4.","5.","6.","7.","8.","9.","10.", | |||
| 6385 | "11.","12.","13.","14.","15.","16.","17.","18.","19.","20.", | |||
| 6386 | "21.","22.","23.","24.","25.","26.","27.","28.","29.","30.", | |||
| 6387 | "31."]]; | |||
| 6388 | $$d{"num_word"}= | |||
| 6389 | [ | |||
| 6390 | ["erste","zweite","dritte","vierte","funfte","sechste","siebente", | |||
| 6391 | "achte","neunte","zehnte","elfte","zwolfte","dreizehnte","vierzehnte", | |||
| 6392 | "funfzehnte","sechzehnte","siebzehnte","achtzehnte","neunzehnte", | |||
| 6393 | "zwanzigste","einundzwanzigste","zweiundzwanzigste","dreiundzwanzigste", | |||
| 6394 | "vierundzwanzigste","funfundzwanzigste","sechundzwanzigste", | |||
| 6395 | "siebundzwanzigste","achtundzwanzigste","neunundzwanzigste", | |||
| 6396 | "dreibigste","einunddreibigste"], | |||
| 6397 | ["erste","zweite","dritte","vierte","f${u}nfte","sechste","siebente", | |||
| 6398 | "achte","neunte","zehnte","elfte","zw${o}lfte","dreizehnte", | |||
| 6399 | "vierzehnte","f${u}nfzehnte","sechzehnte","siebzehnte","achtzehnte", | |||
| 6400 | "neunzehnte","zwanzigste","einundzwanzigste","zweiundzwanzigste", | |||
| 6401 | "dreiundzwanzigste","vierundzwanzigste","f${u}nfundzwanzigste", | |||
| 6402 | "sechundzwanzigste","siebundzwanzigste","achtundzwanzigste", | |||
| 6403 | "neunundzwanzigste","drei${b}igste","einunddrei${b}igste"], | |||
| 6404 | ["erster"]]; | |||
| 6405 | ||||
| 6406 | $$d{"now"} =["jetzt"]; | |||
| 6407 | $$d{"today"} =["heute"]; | |||
| 6408 | $$d{"last"} =["letzte","letzten"]; | |||
| 6409 | $$d{"each"} =["jeden"]; | |||
| 6410 | $$d{"of"} =["der","im","des"]; | |||
| 6411 | $$d{"at"} =["um"]; | |||
| 6412 | $$d{"on"} =["am"]; | |||
| 6413 | $$d{"future"} =["in"]; | |||
| 6414 | $$d{"past"} =["vor"]; | |||
| 6415 | $$d{"next"} =["nachste","n${a}chste","nachsten","n${a}chsten"]; | |||
| 6416 | $$d{"prev"} =["vorherigen","vorherige","letzte","letzten"]; | |||
| 6417 | $$d{"later"} =["spater","sp${a}ter"]; | |||
| 6418 | ||||
| 6419 | $$d{"exact"} =["genau"]; | |||
| 6420 | $$d{"approx"} =["ungefahr","ungef${a}hr"]; | |||
| 6421 | $$d{"business"}=["Arbeitstag"]; | |||
| 6422 | ||||
| 6423 | $$d{"offset"} =["gestern","-0:0:0:1:0:0:0","morgen","+0:0:0:1:0:0:0","${u}bermorgen","+0:0:0:2:0:0:0"]; | |||
| 6424 | $$d{"times"} =["mittag","12:00:00","mitternacht","00:00:00"]; | |||
| 6425 | ||||
| 6426 | $$d{"years"} =["j","Jahr","Jahre","Jahren"]; | |||
| 6427 | $$d{"months"} =["Monat","Monate","Monaten"]; | |||
| 6428 | $$d{"weeks"} =["w","Woche","Wochen"]; | |||
| 6429 | $$d{"days"} =["t","Tag","Tage","Tagen"]; | |||
| 6430 | $$d{"hours"} =["h","std","Stunde","Stunden"]; | |||
| 6431 | $$d{"minutes"} =["min","Minute","Minuten"]; | |||
| 6432 | $$d{"seconds"} =["s","sek","Sekunde","Sekunden"]; | |||
| 6433 | $$d{"replace"} =["m","Monat"]; | |||
| 6434 | ||||
| 6435 | $$d{"sephm"} =':'; | |||
| 6436 | $$d{"sepms"} ='[: ]'; | |||
| 6437 | $$d{"sepss"} ='[.:]'; | |||
| 6438 | ||||
| 6439 | $$d{"am"} = ["FM"]; | |||
| 6440 | $$d{"pm"} = ["EM"]; | |||
| 6441 | } | |||
| 6442 | ||||
| 6443 | sub _Date_Init_Dutch { | |||
| 6444 | print "DEBUG: _Date_Init_Dutch\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6445 | my($d)=@_; | |||
| 6446 | my(%h)=(); | |||
| 6447 | _Char_8Bit(\%h); | |||
| 6448 | ||||
| 6449 | $$d{"month_name"}= | |||
| 6450 | [["januari","februari","maart","april","mei","juni","juli","augustus", | |||
| 6451 | "september","october","november","december"], | |||
| 6452 | ["","","","","","","","","","oktober"]]; | |||
| 6453 | ||||
| 6454 | $$d{"month_abb"}= | |||
| 6455 | [["jan","feb","maa","apr","mei","jun","jul", | |||
| 6456 | "aug","sep","oct","nov","dec"], | |||
| 6457 | ["","","mrt","","","","","","","okt"]]; | |||
| 6458 | $$d{"day_name"}= | |||
| 6459 | [["maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag", | |||
| 6460 | "zondag"]]; | |||
| 6461 | $$d{"day_abb"}= | |||
| 6462 | [["ma","di","wo","do","vr","zat","zon"], | |||
| 6463 | ["","","","","","za","zo"]]; | |||
| 6464 | $$d{"day_char"}= | |||
| 6465 | [["M","D","W","D","V","Za","Zo"]]; | |||
| 6466 | ||||
| 6467 | $$d{"num_suff"}= | |||
| 6468 | [["1ste","2de","3de","4de","5de","6de","7de","8ste","9de","10de", | |||
| 6469 | "11de","12de","13de","14de","15de","16de","17de","18de","19de","20ste", | |||
| 6470 | "21ste","22ste","23ste","24ste","25ste","26ste","27ste","28ste","29ste", | |||
| 6471 | "30ste","31ste"]]; | |||
| 6472 | $$d{"num_word"}= | |||
| 6473 | [["eerste","tweede","derde","vierde","vijfde","zesde","zevende","achtste", | |||
| 6474 | "negende","tiende","elfde","twaalfde", | |||
| 6475 | map {"${_}tiende";} qw (der veer vijf zes zeven acht negen), | |||
| 6476 | "twintigste", | |||
| 6477 | map {"${_}entwintigste";} qw (een twee drie vier vijf zes zeven acht | |||
| 6478 | negen), | |||
| 6479 | "dertigste","eenendertigste"], | |||
| 6480 | ["","","","","","","","","","","","","","","","","","","","", | |||
| 6481 | map {"${_}-en-twintigste";} qw (een twee drie vier vijf zes zeven acht | |||
| 6482 | negen), | |||
| 6483 | "dertigste","een-en-dertigste"], | |||
| 6484 | ["een","twee","drie","vier","vijf","zes","zeven","acht","negen","tien", | |||
| 6485 | "elf","twaalf", | |||
| 6486 | map {"${_}tien"} qw (der veer vijf zes zeven acht negen), | |||
| 6487 | "twintig", | |||
| 6488 | map {"${_}entwintig"} qw (een twee drie vier vijf zes zeven acht negen), | |||
| 6489 | "dertig","eenendertig"], | |||
| 6490 | ["","","","","","","","","","","","","","","","","","","","", | |||
| 6491 | map {"${_}-en-twintig"} qw (een twee drie vier vijf zes zeven acht | |||
| 6492 | negen), | |||
| 6493 | "dertig","een-en-dertig"]]; | |||
| 6494 | ||||
| 6495 | $$d{"now"} =["nu","nou"]; | |||
| 6496 | $$d{"today"} =["vandaag"]; | |||
| 6497 | $$d{"last"} =["laatste"]; | |||
| 6498 | $$d{"each"} =["elke","elk"]; | |||
| 6499 | $$d{"of"} =["in","van"]; | |||
| 6500 | $$d{"at"} =["om"]; | |||
| 6501 | $$d{"on"} =["op"]; | |||
| 6502 | $$d{"future"} =["over"]; | |||
| 6503 | $$d{"past"} =["geleden","vroeger","eerder"]; | |||
| 6504 | $$d{"next"} =["volgende","volgend"]; | |||
| 6505 | $$d{"prev"} =["voorgaande","voorgaand"]; | |||
| 6506 | $$d{"later"} =["later"]; | |||
| 6507 | ||||
| 6508 | $$d{"exact"} =["exact","precies","nauwkeurig"]; | |||
| 6509 | $$d{"approx"} =["ongeveer","ong",'ong\.',"circa","ca",'ca\.']; | |||
| 6510 | $$d{"business"}=["werk","zakelijke","zakelijk"]; | |||
| 6511 | ||||
| 6512 | $$d{"offset"} =["morgen","+0:0:0:1:0:0:0","overmorgen","+0:0:0:2:0:0:0", | |||
| 6513 | "gisteren","-0:0:0:1:0:0:0","eergisteren","-0::00:2:0:0:0"]; | |||
| 6514 | $$d{"times"} =["noen","12:00:00","middernacht","00:00:00"]; | |||
| 6515 | ||||
| 6516 | $$d{"years"} =["jaar","jaren","ja","j"]; | |||
| 6517 | $$d{"months"} =["maand","maanden","mnd"]; | |||
| 6518 | $$d{"weeks"} =["week","weken","w"]; | |||
| 6519 | $$d{"days"} =["dag","dagen","d"]; | |||
| 6520 | $$d{"hours"} =["uur","uren","u","h"]; | |||
| 6521 | $$d{"minutes"} =["minuut","minuten","min"]; | |||
| 6522 | $$d{"seconds"} =["seconde","seconden","sec","s"]; | |||
| 6523 | $$d{"replace"} =["m","minuten"]; | |||
| 6524 | ||||
| 6525 | $$d{"sephm"} ='[:.uh]'; | |||
| 6526 | $$d{"sepms"} ='[:.m]'; | |||
| 6527 | $$d{"sepss"} ='[.:]'; | |||
| 6528 | ||||
| 6529 | $$d{"am"} = ["am","a.m.","vm","v.m.","voormiddag","'s_ochtends", | |||
| 6530 | "ochtend","'s_nachts","nacht"]; | |||
| 6531 | $$d{"pm"} = ["pm","p.m.","nm","n.m.","namiddag","'s_middags","middag", | |||
| 6532 | "'s_avonds","avond"]; | |||
| 6533 | } | |||
| 6534 | ||||
| 6535 | sub _Date_Init_Polish { | |||
| 6536 | print "DEBUG: _Date_Init_Polish\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6537 | my($d)=@_; | |||
| 6538 | ||||
| 6539 | $$d{"month_name"}= | |||
| 6540 | [["stycznia","luty","marca","kwietnia","maja","czerwca", | |||
| 6541 | "lipca","sierpnia","wrzesnia","pazdziernika","listopada","grudnia"], | |||
| 6542 | ["stycznia","luty","marca","kwietnia","maja","czerwca","lipca", | |||
| 6543 | "sierpnia","wrze\x9cnia","pa\x9fdziernika","listopada","grudnia"]]; | |||
| 6544 | $$d{"month_abb"}= | |||
| 6545 | [["sty.","lut.","mar.","kwi.","maj","cze.", | |||
| 6546 | "lip.","sie.","wrz.","paz.","lis.","gru."], | |||
| 6547 | ["sty.","lut.","mar.","kwi.","maj","cze.", | |||
| 6548 | "lip.","sie.","wrz.","pa\x9f.","lis.","gru."]]; | |||
| 6549 | ||||
| 6550 | $$d{"day_name"}= | |||
| 6551 | [["poniedzialek","wtorek","sroda","czwartek","piatek","sobota", | |||
| 6552 | "niedziela"], | |||
| 6553 | ["poniedzia\x81\xb3ek","wtorek","\x9croda","czwartek","pi\x81\xb9tek", | |||
| 6554 | "sobota","niedziela"]]; | |||
| 6555 | $$d{"day_abb"}= | |||
| 6556 | [["po.","wt.","sr.","cz.","pi.","so.","ni."], | |||
| 6557 | ["po.","wt.","\x9cr.","cz.","pi.","so.","ni."]]; | |||
| 6558 | $$d{"day_char"}= | |||
| 6559 | [["p","w","e","c","p","s","n"], | |||
| 6560 | ["p","w","\x9c.","c","p","s","n"]]; | |||
| 6561 | ||||
| 6562 | $$d{"num_suff"}= | |||
| 6563 | [["1.","2.","3.","4.","5.","6.","7.","8.","9.","10.", | |||
| 6564 | "11.","12.","13.","14.","15.","16.","17.","18.","19.","20.", | |||
| 6565 | "21.","22.","23.","24.","25.","26.","27.","28.","29.","30.", | |||
| 6566 | "31."]]; | |||
| 6567 | $$d{"num_word"}= | |||
| 6568 | [["pierwszego","drugiego","trzeczego","czwartego","piatego","szostego", | |||
| 6569 | "siodmego","osmego","dziewiatego","dziesiatego", | |||
| 6570 | "jedenastego","dwunastego","trzynastego","czternastego","pietnastego", | |||
| 6571 | "szestnastego","siedemnastego","osiemnastego","dziewietnastego", | |||
| 6572 | "dwudziestego", | |||
| 6573 | "dwudziestego pierwszego","dwudziestego drugiego", | |||
| 6574 | "dwudziestego trzeczego","dwudziestego czwartego", | |||
| 6575 | "dwudziestego piatego","dwudziestego szostego", | |||
| 6576 | "dwudziestego siodmego","dwudziestego osmego", | |||
| 6577 | "dwudziestego dziewiatego","trzydziestego","trzydziestego pierwszego"], | |||
| 6578 | ["pierwszego","drugiego","trzeczego","czwartego","pi\x81\xb9tego", | |||
| 6579 | "sz\x81\xf3stego","si\x81\xf3dmego","\x81\xf3smego","dziewi\x81\xb9tego", | |||
| 6580 | "dziesi\x81\xb9tego","jedenastego","dwunastego","trzynastego", | |||
| 6581 | "czternastego","pi\x81\xeatnastego","szestnastego","siedemnastego", | |||
| 6582 | "osiemnastego","dziewietnastego","dwudziestego", | |||
| 6583 | "dwudziestego pierwszego","dwudziestego drugiego", | |||
| 6584 | "dwudziestego trzeczego","dwudziestego czwartego", | |||
| 6585 | "dwudziestego pi\x81\xb9tego","dwudziestego sz\x81\xf3stego", | |||
| 6586 | "dwudziestego si\x81\xf3dmego","dwudziestego \x81\xf3smego", | |||
| 6587 | "dwudziestego dziewi\x81\xb9tego","trzydziestego", | |||
| 6588 | "trzydziestego pierwszego"]]; | |||
| 6589 | ||||
| 6590 | $$d{"now"} =["teraz"]; | |||
| 6591 | $$d{"today"} =["dzisaj"]; | |||
| 6592 | $$d{"last"} =["ostatni","ostatna"]; | |||
| 6593 | $$d{"each"} =["kazdy","ka\x81\xbfdy", "kazdym","ka\x81\xbfdym"]; | |||
| 6594 | $$d{"of"} =["w","z"]; | |||
| 6595 | $$d{"at"} =["o","u"]; | |||
| 6596 | $$d{"on"} =["na"]; | |||
| 6597 | $$d{"future"} =["za"]; | |||
| 6598 | $$d{"past"} =["temu"]; | |||
| 6599 | $$d{"next"} =["nastepny","nast\x81\xeapny","nastepnym","nast\x81\xeapnym", | |||
| 6600 | "przyszly","przysz\x81\xb3y","przyszlym", | |||
| 6601 | "przysz\x81\xb3ym"]; | |||
| 6602 | $$d{"prev"} =["zeszly","zesz\x81\xb3y","zeszlym","zesz\x81\xb3ym"]; | |||
| 6603 | $$d{"later"} =["later"]; | |||
| 6604 | ||||
| 6605 | $$d{"exact"} =["doklandnie","dok\x81\xb3andnie"]; | |||
| 6606 | $$d{"approx"} =["w przyblizeniu","w przybli\x81\xbfeniu","mniej wiecej", | |||
| 6607 | "mniej wi\x81\xeacej","okolo","oko\x81\xb3o"]; | |||
| 6608 | $$d{"business"}=["sluzbowy","s\x81\xb3u\x81\xbfbowy","sluzbowym", | |||
| 6609 | "s\x81\xb3u\x81\xbfbowym"]; | |||
| 6610 | ||||
| 6611 | $$d{"times"} =["po\x81\xb3udnie","12:00:00", | |||
| 6612 | "p\x81\xf3\x81\xb3noc","00:00:00", | |||
| 6613 | "poludnie","12:00:00","polnoc","00:00:00"]; | |||
| 6614 | $$d{"offset"} =["wczoraj","-0:0:1:0:0:0","jutro","+0:0:1:0:0:0"]; | |||
| 6615 | ||||
| 6616 | $$d{"years"} =["rok","lat","lata","latach"]; | |||
| 6617 | $$d{"months"} =["m.","miesiac","miesi\x81\xb9c","miesiecy", | |||
| 6618 | "miesi\x81\xeacy","miesiacu","miesi\x81\xb9cu"]; | |||
| 6619 | $$d{"weeks"} =["ty.","tydzien","tydzie\x81\xf1","tygodniu"]; | |||
| 6620 | $$d{"days"} =["d.","dzien","dzie\x81\xf1","dni"]; | |||
| 6621 | $$d{"hours"} =["g.","godzina","godziny","godzinie"]; | |||
| 6622 | $$d{"minutes"} =["mn.","min.","minut","minuty"]; | |||
| 6623 | $$d{"seconds"} =["s.","sekund","sekundy"]; | |||
| 6624 | $$d{"replace"} =["m.","miesiac"]; | |||
| 6625 | ||||
| 6626 | $$d{"sephm"} =':'; | |||
| 6627 | $$d{"sepms"} =':'; | |||
| 6628 | $$d{"sepss"} ='[.:]'; | |||
| 6629 | ||||
| 6630 | $$d{"am"} = ["AM","A.M."]; | |||
| 6631 | $$d{"pm"} = ["PM","P.M."]; | |||
| 6632 | } | |||
| 6633 | ||||
| 6634 | sub _Date_Init_Spanish { | |||
| 6635 | print "DEBUG: _Date_Init_Spanish\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6636 | my($d)=@_; | |||
| 6637 | my(%h)=(); | |||
| 6638 | _Char_8Bit(\%h); | |||
| 6639 | ||||
| 6640 | $$d{"month_name"}= | |||
| 6641 | [["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto", | |||
| 6642 | "Septiembre","Octubre","Noviembre","Diciembre"]]; | |||
| 6643 | ||||
| 6644 | $$d{"month_abb"}= | |||
| 6645 | [["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct", | |||
| 6646 | "Nov","Dic"]]; | |||
| 6647 | ||||
| 6648 | $$d{"day_name"}= | |||
| 6649 | [["Lunes","Martes","Miercoles","Jueves","Viernes","Sabado","Domingo"]]; | |||
| 6650 | $$d{"day_abb"}= | |||
| 6651 | [["Lun","Mar","Mie","Jue","Vie","Sab","Dom"]]; | |||
| 6652 | $$d{"day_char"}= | |||
| 6653 | [["L","Ma","Mi","J","V","S","D"]]; | |||
| 6654 | ||||
| 6655 | $$d{"num_suff"}= | |||
| 6656 | [["1o","2o","3o","4o","5o","6o","7o","8o","9o","10o", | |||
| 6657 | "11o","12o","13o","14o","15o","16o","17o","18o","19o","20o", | |||
| 6658 | "21o","22o","23o","24o","25o","26o","27o","28o","29o","30o","31o"], | |||
| 6659 | ["1a","2a","3a","4a","5a","6a","7a","8a","9a","10a", | |||
| 6660 | "11a","12a","13a","14a","15a","16a","17a","18a","19a","20a", | |||
| 6661 | "21a","22a","23a","24a","25a","26a","27a","28a","29a","30a","31a"]]; | |||
| 6662 | $$d{"num_word"}= | |||
| 6663 | [["Primero","Segundo","Tercero","Cuarto","Quinto","Sexto","Septimo", | |||
| 6664 | "Octavo","Noveno","Decimo","Decimo Primero","Decimo Segundo", | |||
| 6665 | "Decimo Tercero","Decimo Cuarto","Decimo Quinto","Decimo Sexto", | |||
| 6666 | "Decimo Septimo","Decimo Octavo","Decimo Noveno","Vigesimo", | |||
| 6667 | "Vigesimo Primero","Vigesimo Segundo","Vigesimo Tercero", | |||
| 6668 | "Vigesimo Cuarto","Vigesimo Quinto","Vigesimo Sexto", | |||
| 6669 | "Vigesimo Septimo","Vigesimo Octavo","Vigesimo Noveno","Trigesimo", | |||
| 6670 | "Trigesimo Primero"], | |||
| 6671 | ["Primera","Segunda","Tercera","Cuarta","Quinta","Sexta","Septima", | |||
| 6672 | "Octava","Novena","Decima","Decimo Primera","Decimo Segunda", | |||
| 6673 | "Decimo Tercera","Decimo Cuarta","Decimo Quinta","Decimo Sexta", | |||
| 6674 | "Decimo Septima","Decimo Octava","Decimo Novena","Vigesima", | |||
| 6675 | "Vigesimo Primera","Vigesimo Segunda","Vigesimo Tercera", | |||
| 6676 | "Vigesimo Cuarta","Vigesimo Quinta","Vigesimo Sexta", | |||
| 6677 | "Vigesimo Septima","Vigesimo Octava","Vigesimo Novena","Trigesima", | |||
| 6678 | "Trigesimo Primera"]]; | |||
| 6679 | ||||
| 6680 | $$d{"now"} =["Ahora"]; | |||
| 6681 | $$d{"today"} =["Hoy"]; | |||
| 6682 | $$d{"last"} =["ultimo"]; | |||
| 6683 | $$d{"each"} =["cada"]; | |||
| 6684 | $$d{"of"} =["en","de"]; | |||
| 6685 | $$d{"at"} =["a"]; | |||
| 6686 | $$d{"on"} =["el"]; | |||
| 6687 | $$d{"future"} =["en"]; | |||
| 6688 | $$d{"past"} =["hace"]; | |||
| 6689 | $$d{"next"} =["siguiente"]; | |||
| 6690 | $$d{"prev"} =["anterior"]; | |||
| 6691 | $$d{"later"} =["later"]; | |||
| 6692 | ||||
| 6693 | $$d{"exact"} =["exactamente"]; | |||
| 6694 | $$d{"approx"} =["aproximadamente"]; | |||
| 6695 | $$d{"business"}=["laborales"]; | |||
| 6696 | ||||
| 6697 | $$d{"offset"} =["ayer","-0:0:0:1:0:0:0","manana","+0:0:0:1:0:0:0"]; | |||
| 6698 | $$d{"times"} =["mediodia","12:00:00","medianoche","00:00:00"]; | |||
| 6699 | ||||
| 6700 | $$d{"years"} =["a","ano","ano","anos","anos"]; | |||
| 6701 | $$d{"months"} =["m","mes","mes","meses"]; | |||
| 6702 | $$d{"weeks"} =["sem","semana","semana","semanas"]; | |||
| 6703 | $$d{"days"} =["d","dia","dias"]; | |||
| 6704 | $$d{"hours"} =["hr","hrs","hora","horas"]; | |||
| 6705 | $$d{"minutes"} =["min","min","minuto","minutos"]; | |||
| 6706 | $$d{"seconds"} =["s","seg","segundo","segundos"]; | |||
| 6707 | $$d{"replace"} =["m","mes"]; | |||
| 6708 | ||||
| 6709 | $$d{"sephm"} =':'; | |||
| 6710 | $$d{"sepms"} =':'; | |||
| 6711 | $$d{"sepss"} ='[.:]'; | |||
| 6712 | ||||
| 6713 | $$d{"am"} = ["AM","A.M."]; | |||
| 6714 | $$d{"pm"} = ["PM","P.M."]; | |||
| 6715 | } | |||
| 6716 | ||||
| 6717 | sub _Date_Init_Portuguese { | |||
| 6718 | print "DEBUG: _Date_Init_Portuguese\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6719 | my($d)=@_; | |||
| 6720 | my(%h)=(); | |||
| 6721 | _Char_8Bit(\%h); | |||
| 6722 | my($o) = $h{"-o"}; | |||
| 6723 | my($c) = $h{",c"}; | |||
| 6724 | my($a) = $h{"a'"}; | |||
| 6725 | my($e) = $h{"e'"}; | |||
| 6726 | my($u) = $h{"u'"}; | |||
| 6727 | my($o2)= $h{"o'"}; | |||
| 6728 | my($a2)= $h{"a`"}; | |||
| 6729 | my($a3)= $h{"a~"}; | |||
| 6730 | my($e2)= $h{"e^"}; | |||
| 6731 | ||||
| 6732 | $$d{"month_name"}= | |||
| 6733 | [["Janeiro","Fevereiro","Marco","Abril","Maio","Junho", | |||
| 6734 | "Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"], | |||
| 6735 | ["Janeiro","Fevereiro","Mar${c}o","Abril","Maio","Junho", | |||
| 6736 | "Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"]]; | |||
| 6737 | ||||
| 6738 | $$d{"month_abb"}= | |||
| 6739 | [["Jan","Fev","Mar","Abr","Mai","Jun", | |||
| 6740 | "Jul","Ago","Set","Out","Nov","Dez"]]; | |||
| 6741 | ||||
| 6742 | $$d{"day_name"}= | |||
| 6743 | [["Segunda","Terca","Quarta","Quinta","Sexta","Sabado","Domingo"], | |||
| 6744 | ["Segunda","Ter${c}a","Quarta","Quinta","Sexta","S${a}bado","Domingo"]]; | |||
| 6745 | $$d{"day_abb"}= | |||
| 6746 | [["Seg","Ter","Qua","Qui","Sex","Sab","Dom"], | |||
| 6747 | ["Seg","Ter","Qua","Qui","Sex","S${a}b","Dom"]]; | |||
| 6748 | $$d{"day_char"}= | |||
| 6749 | [["Sg","T","Qa","Qi","Sx","Sb","D"]]; | |||
| 6750 | ||||
| 6751 | $$d{"num_suff"}= | |||
| 6752 | [["1${o}","2${o}","3${o}","4${o}","5${o}","6${o}","7${o}","8${o}", | |||
| 6753 | "9${o}","10${o}","11${o}","12${o}","13${o}","14${o}","15${o}", | |||
| 6754 | "16${o}","17${o}","18${o}","19${o}","20${o}","21${o}","22${o}", | |||
| 6755 | "23${o}","24${o}","25${o}","26${o}","27${o}","28${o}","29${o}", | |||
| 6756 | "30${o}","31${o}"]]; | |||
| 6757 | $$d{"num_word"}= | |||
| 6758 | [["primeiro","segundo","terceiro","quarto","quinto","sexto","setimo", | |||
| 6759 | "oitavo","nono","decimo","decimo primeiro","decimo segundo", | |||
| 6760 | "decimo terceiro","decimo quarto","decimo quinto","decimo sexto", | |||
| 6761 | "decimo setimo","decimo oitavo","decimo nono","vigesimo", | |||
| 6762 | "vigesimo primeiro","vigesimo segundo","vigesimo terceiro", | |||
| 6763 | "vigesimo quarto","vigesimo quinto","vigesimo sexto","vigesimo setimo", | |||
| 6764 | "vigesimo oitavo","vigesimo nono","trigesimo","trigesimo primeiro"], | |||
| 6765 | ["primeiro","segundo","terceiro","quarto","quinto","sexto","s${e}timo", | |||
| 6766 | "oitavo","nono","d${e}cimo","d${e}cimo primeiro","d${e}cimo segundo", | |||
| 6767 | "d${e}cimo terceiro","d${e}cimo quarto","d${e}cimo quinto", | |||
| 6768 | "d${e}cimo sexto","d${e}cimo s${e}timo","d${e}cimo oitavo", | |||
| 6769 | "d${e}cimo nono","vig${e}simo","vig${e}simo primeiro", | |||
| 6770 | "vig${e}simo segundo","vig${e}simo terceiro","vig${e}simo quarto", | |||
| 6771 | "vig${e}simo quinto","vig${e}simo sexto","vig${e}simo s${e}timo", | |||
| 6772 | "vig${e}simo oitavo","vig${e}simo nono","trig${e}simo", | |||
| 6773 | "trig${e}simo primeiro"]]; | |||
| 6774 | ||||
| 6775 | $$d{"now"} =["agora"]; | |||
| 6776 | $$d{"today"} =["hoje"]; | |||
| 6777 | $$d{"last"} =["${u}ltimo","ultimo"]; | |||
| 6778 | $$d{"each"} =["cada"]; | |||
| 6779 | $$d{"of"} =["da","do"]; | |||
| 6780 | $$d{"at"} =["as","${a2}s"]; | |||
| 6781 | $$d{"on"} =["na","no"]; | |||
| 6782 | $$d{"future"} =["em"]; | |||
| 6783 | $$d{"past"} =["a","${a2}"]; | |||
| 6784 | $$d{"next"} =["proxima","proximo","pr${o2}xima","pr${o2}ximo"]; | |||
| 6785 | $$d{"prev"} =["ultima","ultimo","${u}ltima","${u}ltimo"]; | |||
| 6786 | $$d{"later"} =["passadas","passados"]; | |||
| 6787 | ||||
| 6788 | $$d{"exact"} =["exactamente"]; | |||
| 6789 | $$d{"approx"} =["aproximadamente"]; | |||
| 6790 | $$d{"business"}=["util","uteis"]; | |||
| 6791 | ||||
| 6792 | $$d{"offset"} =["ontem","-0:0:0:1:0:0:0", | |||
| 6793 | "amanha","+0:0:0:1:0:0:0","amanh${a3}","+0:0:0:1:0:0:0"]; | |||
| 6794 | $$d{"times"} =["meio-dia","12:00:00","meia-noite","00:00:00"]; | |||
| 6795 | ||||
| 6796 | $$d{"years"} =["anos","ano","ans","an","a"]; | |||
| 6797 | $$d{"months"} =["meses","m${e2}s","mes","m"]; | |||
| 6798 | $$d{"weeks"} =["semanas","semana","sem","sems","s"]; | |||
| 6799 | $$d{"days"} =["dias","dia","d"]; | |||
| 6800 | $$d{"hours"} =["horas","hora","hr","hrs"]; | |||
| 6801 | $$d{"minutes"} =["minutos","minuto","min","mn"]; | |||
| 6802 | $$d{"seconds"} =["segundos","segundo","seg","sg"]; | |||
| 6803 | $$d{"replace"} =["m","mes","s","sems"]; | |||
| 6804 | ||||
| 6805 | $$d{"sephm"} =':'; | |||
| 6806 | $$d{"sepms"} =':'; | |||
| 6807 | $$d{"sepss"} ='[,]'; | |||
| 6808 | ||||
| 6809 | $$d{"am"} = ["AM","A.M."]; | |||
| 6810 | $$d{"pm"} = ["PM","P.M."]; | |||
| 6811 | } | |||
| 6812 | ||||
| 6813 | sub _Date_Init_Russian { | |||
| 6814 | print "DEBUG: _Date_Init_Russian\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 6815 | my($d)=@_; | |||
| 6816 | my(%h)=(); | |||
| 6817 | _Char_8Bit(\%h); | |||
| 6818 | my($a) =$h{"a:"}; | |||
| 6819 | ||||
| 6820 | $$d{"month_name"}= | |||
| 6821 | [ | |||
| 6822 | ["\xd1\xce\xd7\xc1\xd2\xd1","\xc6\xc5\xd7\xd2\xc1\xcc\xd1", | |||
| 6823 | "\xcd\xc1\xd2\xd4\xc1","\xc1\xd0\xd2\xc5\xcc\xd1","\xcd\xc1\xd1", | |||
| 6824 | "\xc9\xc0\xce\xd1", | |||
| 6825 | "\xc9\xc0\xcc\xd1","\xc1\xd7\xc7\xd5\xd3\xd4\xc1", | |||
| 6826 | "\xd3\xc5\xce\xd4\xd1\xc2\xd2\xd1","\xcf\xcb\xd4\xd1\xc2\xd2\xd1", | |||
| 6827 | "\xce\xcf\xd1\xc2\xd2\xd1","\xc4\xc5\xcb\xc1\xc2\xd2\xd1"], | |||
| 6828 | ["\xd1\xce\xd7\xc1\xd2\xd8","\xc6\xc5\xd7\xd2\xc1\xcc\xd8", | |||
| 6829 | "\xcd\xc1\xd2\xd4","\xc1\xd0\xd2\xc5\xcc\xd8","\xcd\xc1\xca", | |||
| 6830 | "\xc9\xc0\xce\xd8", | |||
| 6831 | "\xc9\xc0\xcc\xd8","\xc1\xd7\xc7\xd5\xd3\xd4", | |||
| 6832 | "\xd3\xc5\xce\xd4\xd1\xc2\xd2\xd8","\xcf\xcb\xd4\xd1\xc2\xd2\xd8", | |||
| 6833 | "\xce\xcf\xd1\xc2\xd2\xd8","\xc4\xc5\xcb\xc1\xc2\xd2\xd8"] | |||
| 6834 | ]; | |||
| 6835 | ||||
| 6836 | $$d{"month_abb"}= | |||
| 6837 | [["\xd1\xce\xd7","\xc6\xc5\xd7","\xcd\xd2\xd4","\xc1\xd0\xd2", | |||
| 6838 | "\xcd\xc1\xca","\xc9\xc0\xce", | |||
| 6839 | "\xc9\xc0\xcc","\xc1\xd7\xc7","\xd3\xce\xd4","\xcf\xcb\xd4", | |||
| 6840 | "\xce\xcf\xd1\xc2","\xc4\xc5\xcb"], | |||
| 6841 | ["","\xc6\xd7\xd2","","","\xcd\xc1\xd1","", | |||
| 6842 | "","","\xd3\xc5\xce","\xcf\xcb\xd4","\xce\xcf\xd1",""]]; | |||
| 6843 | ||||
| 6844 | $$d{"day_name"}= | |||
| 6845 | [["\xd0\xcf\xce\xc5\xc4\xc5\xcc\xd8\xce\xc9\xcb", | |||
| 6846 | "\xd7\xd4\xcf\xd2\xce\xc9\xcb","\xd3\xd2\xc5\xc4\xc1", | |||
| 6847 | "\xde\xc5\xd4\xd7\xc5\xd2\xc7","\xd0\xd1\xd4\xce\xc9\xc3\xc1", | |||
| 6848 | "\xd3\xd5\xc2\xc2\xcf\xd4\xc1", | |||
| 6849 | "\xd7\xcf\xd3\xcb\xd2\xc5\xd3\xc5\xce\xd8\xc5"]]; | |||
| 6850 | $$d{"day_abb"}= | |||
| 6851 | [["\xd0\xce\xc4","\xd7\xd4\xd2","\xd3\xd2\xc4","\xde\xd4\xd7", | |||
| 6852 | "\xd0\xd4\xce","\xd3\xd5\xc2","\xd7\xd3\xcb"], | |||
| 6853 | ["\xd0\xcf\xce","\xd7\xd4\xcf","\xd3\xd2e","\xde\xc5\xd4", | |||
| 6854 | "\xd0\xd1\xd4","\xd3\xd5\xc2","\xd7\xcf\xd3\xcb"]]; | |||
| 6855 | $$d{"day_char"}= | |||
| 6856 | [["\xd0\xce","\xd7\xd4","\xd3\xd2","\xde\xd4","\xd0\xd4","\xd3\xc2", | |||
| 6857 | "\xd7\xd3"]]; | |||
| 6858 | ||||
| 6859 | $$d{"num_suff"}= | |||
| 6860 | [["1 ","2 ","3 ","4 ","5 ","6 ","7 ","8 ","9 ","10 ", | |||
| 6861 | "11 ","12 ","13 ","14 ","15 ","16 ","17 ","18 ","19 ","20 ", | |||
| 6862 | "21 ","22 ","23 ","24 ","25 ","26 ","27 ","28 ","29 ","30 ", | |||
| 6863 | "31 "]]; | |||
| 6864 | $$d{"num_word"}= | |||
| 6865 | [["\xd0\xc5\xd2\xd7\xd9\xca","\xd7\xd4\xcf\xd2\xcf\xca", | |||
| 6866 | "\xd4\xd2\xc5\xd4\xc9\xca","\xde\xc5\xd4\xd7\xc5\xd2\xd4\xd9\xca", | |||
| 6867 | "\xd0\xd1\xd4\xd9\xca","\xdb\xc5\xd3\xd4\xcf\xca", | |||
| 6868 | "\xd3\xc5\xc4\xd8\xcd\xcf\xca","\xd7\xcf\xd3\xd8\xcd\xcf\xca", | |||
| 6869 | "\xc4\xc5\xd7\xd1\xd4\xd9\xca","\xc4\xc5\xd3\xd1\xd4\xd9\xca", | |||
| 6870 | "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6871 | "\xc4\xd7\xc5\xce\xc1\xc4\xde\xc1\xd4\xd9\xca", | |||
| 6872 | "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6873 | "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6874 | "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6875 | "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6876 | "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6877 | "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6878 | "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6879 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6880 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xd9\xca", | |||
| 6881 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xca", | |||
| 6882 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xc9\xca", | |||
| 6883 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xd9\xca", | |||
| 6884 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xd9\xca", | |||
| 6885 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xca", | |||
| 6886 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xca", | |||
| 6887 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xca", | |||
| 6888 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xd9\xca", | |||
| 6889 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd9\xca", | |||
| 6890 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xd9\xca"], | |||
| 6891 | ||||
| 6892 | ["\xd0\xc5\xd2\xd7\xcf\xc5","\xd7\xd4\xcf\xd2\xcf\xc5", | |||
| 6893 | "\xd4\xd2\xc5\xd4\xd8\xc5","\xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc5", | |||
| 6894 | "\xd0\xd1\xd4\xcf\xc5","\xdb\xc5\xd3\xd4\xcf\xc5", | |||
| 6895 | "\xd3\xc5\xc4\xd8\xcd\xcf\xc5","\xd7\xcf\xd3\xd8\xcd\xcf\xc5", | |||
| 6896 | "\xc4\xc5\xd7\xd1\xd4\xcf\xc5","\xc4\xc5\xd3\xd1\xd4\xcf\xc5", | |||
| 6897 | "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6898 | "\xc4\xd7\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6899 | "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6900 | "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6901 | "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6902 | "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6903 | "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6904 | "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6905 | "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6906 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6907 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc5", | |||
| 6908 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xc5", | |||
| 6909 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xd8\xc5", | |||
| 6910 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc5", | |||
| 6911 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xcf\xc5", | |||
| 6912 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xc5", | |||
| 6913 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xc5", | |||
| 6914 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xc5", | |||
| 6915 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xcf\xc5", | |||
| 6916 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xcf\xc5", | |||
| 6917 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc5"], | |||
| 6918 | ||||
| 6919 | ["\xd0\xc5\xd2\xd7\xcf\xc7\xcf","\xd7\xd4\xcf\xd2\xcf\xc7\xcf", | |||
| 6920 | "\xd4\xd2\xc5\xd4\xd8\xc5\xc7\xcf", | |||
| 6921 | "\xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc7\xcf","\xd0\xd1\xd4\xcf\xc7\xcf", | |||
| 6922 | "\xdb\xc5\xd3\xd4\xcf\xc7\xcf","\xd3\xc5\xc4\xd8\xcd\xcf\xc7\xcf", | |||
| 6923 | "\xd7\xcf\xd3\xd8\xcd\xcf\xc7\xcf", | |||
| 6924 | "\xc4\xc5\xd7\xd1\xd4\xcf\xc7\xcf","\xc4\xc5\xd3\xd1\xd4\xcf\xc7\xcf", | |||
| 6925 | "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6926 | "\xc4\xd7\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6927 | "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6928 | "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6929 | "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6930 | "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6931 | "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6932 | "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6933 | "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6934 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6935 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc7\xcf", | |||
| 6936 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xc5", | |||
| 6937 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xd8\xc5\xc7\xcf", | |||
| 6938 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc7\xcf", | |||
| 6939 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xcf\xc7\xcf", | |||
| 6940 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xc7\xcf", | |||
| 6941 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xc7\xcf", | |||
| 6942 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xc7\xcf", | |||
| 6943 | "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xcf\xc7\xcf", | |||
| 6944 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xcf\xc7\xcf", | |||
| 6945 | "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc7\xcf"]]; | |||
| 6946 | ||||
| 6947 | $$d{"now"} =["\xd3\xc5\xca\xde\xc1\xd3"]; | |||
| 6948 | $$d{"today"} =["\xd3\xc5\xc7\xcf\xc4\xce\xd1"]; | |||
| 6949 | $$d{"last"} =["\xd0\xcf\xd3\xcc\xc5\xc4\xce\xc9\xca"]; | |||
| 6950 | $$d{"each"} =["\xcb\xc1\xd6\xc4\xd9\xca"]; | |||
| 6951 | $$d{"of"} =[" "]; | |||
| 6952 | $$d{"at"} =["\xd7"]; | |||
| 6953 | $$d{"on"} =["\xd7"]; | |||
| 6954 | $$d{"future"} =["\xd7\xd0\xc5\xd2\xc5\xc4 \xce\xc1"]; | |||
| 6955 | $$d{"past"} =["\xce\xc1\xda\xc1\xc4 \xce\xc1 "]; | |||
| 6956 | $$d{"next"} =["\xd3\xcc\xc5\xc4\xd5\xc0\xdd\xc9\xca"]; | |||
| 6957 | $$d{"prev"} =["\xd0\xd2\xc5\xc4\xd9\xc4\xd5\xdd\xc9\xca"]; | |||
| 6958 | $$d{"later"} =["\xd0\xcf\xda\xd6\xc5"]; | |||
| 6959 | ||||
| 6960 | $$d{"exact"} =["\xd4\xcf\xde\xce\xcf"]; | |||
| 6961 | $$d{"approx"} =["\xd0\xd2\xc9\xcd\xc5\xd2\xce\xcf"]; | |||
| 6962 | $$d{"business"}=["\xd2\xc1\xc2\xcf\xde\xc9\xc8"]; | |||
| 6963 | ||||
| 6964 | $$d{"offset"} =["\xd0\xcf\xda\xc1\xd7\xde\xc5\xd2\xc1","-0:0:0:2:0:0:0", | |||
| 6965 | "\xd7\xde\xc5\xd2\xc1","-0:0:0:1:0:0:0", | |||
| 6966 | "\xda\xc1\xd7\xd4\xd2\xc1","+0:0:0:1:0:0:0", | |||
| 6967 | "\xd0\xcf\xd3\xcc\xc5\xda\xc1\xd7\xd4\xd2\xc1", | |||
| 6968 | "+0:0:0:2:0:0:0"]; | |||
| 6969 | $$d{"times"} =["\xd0\xcf\xcc\xc4\xc5\xce\xd8","12:00:00", | |||
| 6970 | "\xd0\xcf\xcc\xce\xcf\xde\xd8","00:00:00"]; | |||
| 6971 | ||||
| 6972 | $$d{"years"} =["\xc7","\xc7\xc4","\xc7\xcf\xc4","\xcc\xc5\xd4", | |||
| 6973 | "\xcc\xc5\xd4","\xc7\xcf\xc4\xc1"]; | |||
| 6974 | $$d{"months"} =["\xcd\xc5\xd3","\xcd\xc5\xd3\xd1\xc3", | |||
| 6975 | "\xcd\xc5\xd3\xd1\xc3\xc5\xd7"]; | |||
| 6976 | $$d{"weeks"} =["\xce\xc5\xc4\xc5\xcc\xd1","\xce\xc5\xc4\xc5\xcc\xd8", | |||
| 6977 | "\xce\xc5\xc4\xc5\xcc\xc9","\xce\xc5\xc4\xc5\xcc\xc0"]; | |||
| 6978 | $$d{"days"} =["\xc4","\xc4\xc5\xce\xd8","\xc4\xce\xc5\xca", | |||
| 6979 | "\xc4\xce\xd1"]; | |||
| 6980 | $$d{"hours"} =["\xde","\xde.","\xde\xd3","\xde\xd3\xd7","\xde\xc1\xd3", | |||
| 6981 | "\xde\xc1\xd3\xcf\xd7","\xde\xc1\xd3\xc1"]; | |||
| 6982 | $$d{"minutes"} =["\xcd\xce","\xcd\xc9\xce","\xcd\xc9\xce\xd5\xd4\xc1", | |||
| 6983 | "\xcd\xc9\xce\xd5\xd4"]; | |||
| 6984 | $$d{"seconds"} =["\xd3","\xd3\xc5\xcb","\xd3\xc5\xcb\xd5\xce\xc4\xc1", | |||
| 6985 | "\xd3\xc5\xcb\xd5\xce\xc4"]; | |||
| 6986 | $$d{"replace"} =[]; | |||
| 6987 | ||||
| 6988 | $$d{"sephm"} ="[:\xde]"; | |||
| 6989 | $$d{"sepms"} ="[:\xcd]"; | |||
| 6990 | $$d{"sepss"} ="[:.\xd3]"; | |||
| 6991 | ||||
| 6992 | $$d{"am"} = ["\xc4\xd0","${a}\xf0","${a}.\xf0.","\xce\xcf\xde\xc9", | |||
| 6993 | "\xd5\xd4\xd2\xc1", | |||
| 6994 | "\xc4\xcf \xd0\xcf\xcc\xd5\xc4\xce\xd1"]; | |||
| 6995 | $$d{"pm"} = ["\xd0\xd0","\xf0\xf0","\xf0.\xf0.","\xc4\xce\xd1", | |||
| 6996 | "\xd7\xc5\xde\xc5\xd2\xc1", | |||
| 6997 | "\xd0\xcf\xd3\xcc\xc5 \xd0\xcf\xcc\xd5\xc4\xce\xd1", | |||
| 6998 | "\xd0\xcf \xd0\xcf\xcc\xd5\xc4\xce\xc0"]; | |||
| 6999 | } | |||
| 7000 | ||||
| 7001 | sub _Date_Init_Turkish { | |||
| 7002 | print "DEBUG: _Date_Init_Turkish\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 7003 | my($d)=@_; | |||
| 7004 | ||||
| 7005 | $$d{"month_name"}= | |||
| 7006 | [ | |||
| 7007 | ["ocak","subat","mart","nisan","mayis","haziran", | |||
| 7008 | "temmuz","agustos","eylul","ekim","kasim","aralik"], | |||
| 7009 | ["ocak","\xfeubat","mart","nisan","may\xfds","haziran", | |||
| 7010 | "temmuz","a\xf0ustos","eyl\xfcl","ekim","kas\xfdm","aral\xfdk"] | |||
| 7011 | ]; | |||
| 7012 | ||||
| 7013 | $$d{"month_abb"}= | |||
| 7014 | [ | |||
| 7015 | ["oca","sub","mar","nis","may","haz", | |||
| 7016 | "tem","agu","eyl","eki","kas","ara"], | |||
| 7017 | ["oca","\xfeub","mar","nis","may","haz", | |||
| 7018 | "tem","a\xf0u","eyl","eki","kas","ara"] | |||
| 7019 | ]; | |||
| 7020 | ||||
| 7021 | $$d{"day_name"}= | |||
| 7022 | [ | |||
| 7023 | ["pazartesi","sali","carsamba","persembe","cuma","cumartesi","pazar"], | |||
| 7024 | ["pazartesi","sal\xfd","\xe7ar\xfeamba","per\xfeembe","cuma", | |||
| 7025 | "cumartesi","pazar"], | |||
| 7026 | ]; | |||
| 7027 | ||||
| 7028 | $$d{"day_abb"}= | |||
| 7029 | [ | |||
| 7030 | ["pzt","sal","car","per","cum","cts","paz"], | |||
| 7031 | ["pzt","sal","\xe7ar","per","cum","cts","paz"], | |||
| 7032 | ]; | |||
| 7033 | ||||
| 7034 | $$d{"day_char"}= | |||
| 7035 | [["Pt","S","Cr","Pr","C","Ct","P"], | |||
| 7036 | ["Pt","S","\xc7","Pr","C","Ct","P"]]; | |||
| 7037 | ||||
| 7038 | $$d{"num_suff"}= | |||
| 7039 | [[ "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.", | |||
| 7040 | "11.", "12.", "13.", "14.", "15.", "16.", "17.", "18.", "19.", "20.", | |||
| 7041 | "21.", "22.", "23.", "24.", "25.", "26.", "27.", "28.", "29.", "30.", | |||
| 7042 | "31."]]; | |||
| 7043 | ||||
| 7044 | $$d{"num_word"}= | |||
| 7045 | [ | |||
| 7046 | ["birinci","ikinci","ucuncu","dorduncu", | |||
| 7047 | "besinci","altinci","yedinci","sekizinci", | |||
| 7048 | "dokuzuncu","onuncu","onbirinci","onikinci", | |||
| 7049 | "onucuncu","ondordoncu", | |||
| 7050 | "onbesinci","onaltinci","onyedinci","onsekizinci", | |||
| 7051 | "ondokuzuncu","yirminci","yirmibirinci","yirmikinci", | |||
| 7052 | "yirmiucuncu","yirmidorduncu", | |||
| 7053 | "yirmibesinci","yirmialtinci","yirmiyedinci","yirmisekizinci", | |||
| 7054 | "yirmidokuzuncu","otuzuncu","otuzbirinci"], | |||
| 7055 | ["birinci","ikinci","\xfc\xe7\xfcnc\xfc","d\xf6rd\xfcnc\xfc", | |||
| 7056 | "be\xfeinci","alt\xfdnc\xfd","yedinci","sekizinci", | |||
| 7057 | "dokuzuncu","onuncu","onbirinci","onikinci", | |||
| 7058 | "on\xfc\xe7\xfcnc\xfc","ond\xf6rd\xfcnc\xfc", | |||
| 7059 | "onbe\xfeinci","onalt\xfdnc\xfd","onyedinci","onsekizinci", | |||
| 7060 | "ondokuzuncu","yirminci","yirmibirinci","yirmikinci", | |||
| 7061 | "yirmi\xfc\xe7\xfcnc\xfc","yirmid\xf6rd\xfcnc\xfc", | |||
| 7062 | "yirmibe\xfeinci","yirmialt\xfdnc\xfd","yirmiyedinci","yirmisekizinci", | |||
| 7063 | "yirmidokuzuncu","otuzuncu","otuzbirinci"] | |||
| 7064 | ]; | |||
| 7065 | ||||
| 7066 | $$d{"now"} =["\xfeimdi", "simdi"]; | |||
| 7067 | $$d{"today"} =["bugun", "bug\xfcn"]; | |||
| 7068 | $$d{"last"} =["son", "sonuncu"]; | |||
| 7069 | $$d{"each"} =["her"]; | |||
| 7070 | $$d{"of"} =["of"]; | |||
| 7071 | $$d{"at"} =["saat"]; | |||
| 7072 | $$d{"on"} =["on"]; | |||
| 7073 | $$d{"future"} =["gelecek"]; | |||
| 7074 | $$d{"past"} =["ge\xe7mi\xfe", "gecmis","gecen", "ge\xe7en"]; | |||
| 7075 | $$d{"next"} =["gelecek","sonraki"]; | |||
| 7076 | $$d{"prev"} =["onceki","\xf6nceki"]; | |||
| 7077 | $$d{"later"} =["sonra"]; | |||
| 7078 | ||||
| 7079 | $$d{"exact"} =["tam"]; | |||
| 7080 | $$d{"approx"} =["yakla\xfe\xfdk", "yaklasik"]; | |||
| 7081 | $$d{"business"}=["i\xfe","\xe7al\xfd\xfema","is", "calisma"]; | |||
| 7082 | ||||
| 7083 | $$d{"offset"} =["d\xfcn","-0:0:0:1:0:0:0", | |||
| 7084 | "dun", "-0:0:0:1:0:0:0", | |||
| 7085 | "yar\xfdn","+0:0:0:1:0:0:0", | |||
| 7086 | "yarin","+0:0:0:1:0:0:0"]; | |||
| 7087 | ||||
| 7088 | $$d{"times"} =["\xf6\xf0len","12:00:00", | |||
| 7089 | "oglen","12:00:00", | |||
| 7090 | "yarim","12:300:00", | |||
| 7091 | "yar\xfdm","12:30:00", | |||
| 7092 | "gece yar\xfds\xfd","00:00:00", | |||
| 7093 | "gece yarisi","00:00:00"]; | |||
| 7094 | ||||
| 7095 | $$d{"years"} =["yil","y"]; | |||
| 7096 | $$d{"months"} =["ay","a"]; | |||
| 7097 | $$d{"weeks"} =["hafta", "h"]; | |||
| 7098 | $$d{"days"} =["gun","g"]; | |||
| 7099 | $$d{"hours"} =["saat"]; | |||
| 7100 | $$d{"minutes"} =["dakika","dak","d"]; | |||
| 7101 | $$d{"seconds"} =["saniye","sn",]; | |||
| 7102 | $$d{"replace"} =["s","saat"]; | |||
| 7103 | ||||
| 7104 | $$d{"sephm"} =':'; | |||
| 7105 | $$d{"sepms"} =':'; | |||
| 7106 | $$d{"sepss"} ='[.:,]'; | |||
| 7107 | ||||
| 7108 | $$d{"am"} = ["\xf6gleden \xf6nce","ogleden once"]; | |||
| 7109 | $$d{"pm"} = ["\xf6\xf0leden sonra","ogleden sonra"]; | |||
| 7110 | } | |||
| 7111 | ||||
| 7112 | sub _Date_Init_Danish { | |||
| 7113 | print "DEBUG: _Date_Init_Danish\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 7114 | my($d)=@_; | |||
| 7115 | ||||
| 7116 | $$d{"month_name"}= | |||
| 7117 | [["Januar","Februar","Marts","April","Maj","Juni", | |||
| 7118 | "Juli","August","September","Oktober","November","December"]]; | |||
| 7119 | $$d{"month_abb"}= | |||
| 7120 | [["Jan","Feb","Mar","Apr","Maj","Jun", | |||
| 7121 | "Jul","Aug","Sep","Okt","Nov","Dec"]]; | |||
| 7122 | ||||
| 7123 | $$d{"day_name"}= | |||
| 7124 | [["Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lordag","Sondag"], | |||
| 7125 | ["Mandag","Tirsdag","Onsdag","Torsdag","Fredag","L\xf8rdag","S\xf8ndag"]]; | |||
| 7126 | ||||
| 7127 | $$d{"day_abb"}= | |||
| 7128 | [["Man","Tir","Ons","Tor","Fre","Lor","Son"], | |||
| 7129 | ["Man","Tir","Ons","Tor","Fre","L\xf8r","S\xf8n"]]; | |||
| 7130 | $$d{"day_char"}= | |||
| 7131 | [["M","Ti","O","To","F","L","S"]]; | |||
| 7132 | ||||
| 7133 | $$d{"num_suff"}= | |||
| 7134 | [["1:e","2:e","3:e","4:e","5:e","6:e","7:e","8:e","9:e","10:e", | |||
| 7135 | "11:e","12:e","13:e","14:e","15:e","16:e","17:e","18:e","19:e","20:e", | |||
| 7136 | "21:e","22:e","23:e","24:e","25:e","26:e","27:e","28:e","29:e","30:e", | |||
| 7137 | "31:e"]]; | |||
| 7138 | $$d{"num_word"}= | |||
| 7139 | [["forste","anden","tredie","fjerde","femte","sjette","syvende", | |||
| 7140 | "ottende","niende","tiende","elfte","tolvte","trettende","fjortende", | |||
| 7141 | "femtende","sekstende","syttende","attende","nittende","tyvende", | |||
| 7142 | "enogtyvende","toogtyvende","treogtyvende","fireogtyvende","femogtyvende", | |||
| 7143 | "seksogtyvende","syvogtyvende","otteogtyvende","niogtyvende", | |||
| 7144 | "tredivte","enogtredivte"], | |||
| 7145 | ["f\xf8rste","anden","tredie","fjerde","femte","sjette","syvende", | |||
| 7146 | "ottende","niende","tiende","elfte","tolvte","trettende","fjortende", | |||
| 7147 | "femtende","sekstende","syttende","attende","nittende","tyvende", | |||
| 7148 | "enogtyvende","toogtyvende","treogtyvende","fireogtyvende","femogtyvende", | |||
| 7149 | "seksogtyvende","syvogtyvende","otteogtyvende","niogtyvende", | |||
| 7150 | "tredivte","enogtredivte"]]; | |||
| 7151 | ||||
| 7152 | $$d{"now"} =["nu"]; | |||
| 7153 | $$d{"today"} =["idag"]; | |||
| 7154 | $$d{"last"} =["forrige","sidste","nyeste"]; | |||
| 7155 | $$d{"each"} =["hver"]; | |||
| 7156 | $$d{"of"} =["om"]; | |||
| 7157 | $$d{"at"} =["kl","kl.","klokken"]; | |||
| 7158 | $$d{"on"} =["pa","p\xe5"]; | |||
| 7159 | $$d{"future"} =["om"]; | |||
| 7160 | $$d{"past"} =["siden"]; | |||
| 7161 | $$d{"next"} =["nasta","n\xe6ste"]; | |||
| 7162 | $$d{"prev"} =["forrige"]; | |||
| 7163 | $$d{"later"} =["senere"]; | |||
| 7164 | ||||
| 7165 | $$d{"exact"} =["pracist","pr\xe6cist"]; | |||
| 7166 | $$d{"approx"} =["circa"]; | |||
| 7167 | $$d{"business"}=["arbejdsdag","arbejdsdage"]; | |||
| 7168 | ||||
| 7169 | $$d{"offset"} =["ig\xe5r","-0:0:0:1:0:0:0","igar","-0:0:0:1:0:0:0", | |||
| 7170 | "imorgen","+0:0:0:1:0:0:0"]; | |||
| 7171 | $$d{"times"} =["midt pa dagen","12:00:00","midt p\xe5 dagen","12:00:00", | |||
| 7172 | "midnat","00:00:00"]; | |||
| 7173 | ||||
| 7174 | $$d{"years"} =["ar","\xe5r"]; | |||
| 7175 | $$d{"months"} =["man","maned","maneder","m\xe5n","m\xe5ned","m\xe5neder"]; | |||
| 7176 | $$d{"weeks"} =["u","uge","uger"]; | |||
| 7177 | $$d{"days"} =["d","dag","dage"]; | |||
| 7178 | $$d{"hours"} =["t","tim","time","timer"]; | |||
| 7179 | $$d{"minutes"} =["min","minut","minutter"]; | |||
| 7180 | $$d{"seconds"} =["s","sek","sekund","sekunder"]; | |||
| 7181 | $$d{"replace"} =["m","minut"]; | |||
| 7182 | ||||
| 7183 | $$d{"sephm"} ='[.:]'; | |||
| 7184 | $$d{"sepms"} =':'; | |||
| 7185 | $$d{"sepss"} ='[.:]'; | |||
| 7186 | ||||
| 7187 | $$d{"am"} = ["FM"]; | |||
| 7188 | $$d{"pm"} = ["EM"]; | |||
| 7189 | } | |||
| 7190 | ||||
| 7191 | sub _Date_Init_Catalan { | |||
| 7192 | print "DEBUG: _Date_Init_Catalan\n" if ($Curr{"Debug"} =~ /trace/); | |||
| 7193 | my($d)=@_; | |||
| 7194 | ||||
| 7195 | $$d{"month_name"}= | |||
| 7196 | [["Gener","Febrer","Marc","Abril","Maig","Juny", | |||
| 7197 | "Juliol","Agost","Setembre","Octubre","Novembre","Desembre"], | |||
| 7198 | ["Gener","Febrer","Març","Abril","Maig","Juny", | |||
| 7199 | "Juliol","Agost","Setembre","Octubre","Novembre","Desembre"], | |||
| 7200 | ["Gener","Febrer","Marc,","Abril","Maig","Juny", | |||
| 7201 | "Juliol","Agost","Setembre","Octubre","Novembre","Desembre"]]; | |||
| 7202 | ||||
| 7203 | $$d{"month_abb"}= | |||
| 7204 | [["Gen","Feb","Mar","Abr","Mai","Jun", | |||
| 7205 | "Jul","Ago","Set","Oct","Nov","Des"], | |||
| 7206 | [], | |||
| 7207 | ["","","","","","", | |||
| 7208 | "","","","","","Dec"] #common mistake | |||
| 7209 | ]; | |||
| 7210 | ||||
| 7211 | $$d{"day_name"}= | |||
| 7212 | [["Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte","Diumenge"]]; | |||
| 7213 | $$d{"day_abb"}= | |||
| 7214 | [["Dll","Dmt","Dmc","Dij","Div","Dis","Diu"], | |||
| 7215 | ["","Dim","","","","",""], | |||
| 7216 | ["","","Dic","","","",""] | |||
| 7217 | ]; | |||
| 7218 | $$d{"day_char"}= | |||
| 7219 | [["Dl","Dm","Dc","Dj","Dv","Ds","Du"] , | |||
| 7220 | ["L","M","X","J","V","S","U"]]; | |||
| 7221 | ||||
| 7222 | $$d{"num_suff"}= | |||
| 7223 | [["1er","2n","3r","4t","5e","6e","7e","8e","9e","10e", | |||
| 7224 | "11e","12e","13e","14e","15e","16e","17e","18e","19e","20e", | |||
| 7225 | "21e","22e","23e","24e","25e","26e","27e","28e","29e","30e", | |||
| 7226 | "31e"], | |||
| 7227 | ["1er","2n","3r","4t","5è","6è","7è","8è","9è","10è", | |||
| 7228 | "11è","12è","13è","14è","15è","16è","17è","18è","19è","20è", | |||
| 7229 | "21è","22è","23è","24è","25è","26è","27è","28è","29è","30è", | |||
| 7230 | "31è"]]; | |||
| 7231 | $$d{"num_word"}= | |||
| 7232 | [["primer","segon","tercer","quart","cinque","sise","sete","vuite", | |||
| 7233 | "nove","dese","onze","dotze","tretze","catorze", | |||
| 7234 | "quinze","setze","dissete","divuite","dinove", | |||
| 7235 | "vinte","vint-i-une","vint-i-dose","vint-i-trese", | |||
| 7236 | "vint-i-quatre","vint-i-cinque","vint-i-sise","vint-i-sete", | |||
| 7237 | "vint-i-vuite","vint-i-nove","trente","trenta-une"], | |||
| 7238 | ["primer","segon","tercer","quart","cinquè","sisè","setè","vuitè", | |||
| 7239 | "novè","desè","onzè","dotzè","tretzè","catorzè", | |||
| 7240 | "quinzè","setzè","dissetè","divuitè","dinovè", | |||
| 7241 | "vintè","vint-i-unè","vint-i-dosè","vint-i-tresè", | |||
| 7242 | "vint-i-quatrè","vint-i-cinquè","vint-i-sisè","vint-i-setè", | |||
| 7243 | "vint-i-vuitè","vint-i-novè","trentè","trenta-unè"]]; | |||
| 7244 | ||||
| 7245 | $$d{"now"} =["avui","ara"]; | |||
| 7246 | $$d{"last"} =["darrer","últim","darrera","última"]; | |||
| 7247 | $$d{"each"} =["cada","cadascun","cadascuna"]; | |||
| 7248 | $$d{"of"} =["de","d'"]; | |||
| 7249 | $$d{"at"} =["a les","a","al"]; | |||
| 7250 | $$d{"on"} =["el"]; | |||
| 7251 | $$d{"future"} =["d'aquí a"]; | |||
| 7252 | $$d{"past"} =["fa"]; | |||
| 7253 | $$d{"next"} =["proper"]; | |||
| 7254 | $$d{"prev"} =["passat","proppassat","anterior"]; | |||
| 7255 | $$d{"later"} =["més tard"]; | |||
| 7256 | ||||
| 7257 | $$d{"exact"} =["exactament"]; | |||
| 7258 | $$d{"approx"} =["approximadament"]; | |||
| 7259 | $$d{"business"}=["empresa"]; | |||
| 7260 | ||||
| 7261 | $$d{"offset"} =["ahir","-0:0:0:1:0:0:0","demà","+0:0:0:1:0:0:0","abans d'ahir","-0:0:0:2:0:0:0","demà passat","+0:0:0:2:0:0:0",]; | |||
| 7262 | $$d{"times"} =["migdia","12:00:00","mitjanit","00:00:00"]; | |||
| 7263 | ||||
| 7264 | $$d{"years"} =["a","an","any","anys"]; | |||
| 7265 | $$d{"months"} =["mes","me","ms"]; | |||
| 7266 | $$d{"weeks"} =["se","set","setm","setmana","setmanes"]; | |||
| 7267 | $$d{"days"} =["d","dia","dies"]; | |||
| 7268 | $$d{"hours"} =["h","ho","hores","hora"]; | |||
| 7269 | $$d{"minutes"} =["mn","min","minut","minuts"]; | |||
| 7270 | $$d{"seconds"} =["s","seg","segon","segons"]; | |||
| 7271 | $$d{"replace"} =["m","mes","s","setmana"]; | |||
| 7272 | ||||
| 7273 | $$d{"sephm"} =':'; | |||
| 7274 | $$d{"sepms"} =':'; | |||
| 7275 | $$d{"sepss"} ='[.:]'; | |||
| 7276 | ||||
| 7277 | $$d{"am"} = ["AM","A.M."]; | |||
| 7278 | $$d{"pm"} = ["PM","P.M."]; | |||
| 7279 | } | |||
| 7280 | ||||
| 7281 | ######################################################################## | |||
| 7282 | # FROM MY PERSONAL LIBRARIES | |||
| 7283 | ######################################################################## | |||
| 7284 | ||||
| 7285 | 3 | 1.71ms | 572µs | no integer; # spent 23µs making 1 call to integer::unimport |
| 7286 | ||||
| 7287 | # _ModuloAddition($N,$add,\$val,\$rem); | |||
| 7288 | # This calculates $val=$val+$add and forces $val to be in a certain range. | |||
| 7289 | # This is useful for adding numbers for which only a certain range is | |||
| 7290 | # allowed (for example, minutes can be between 0 and 59 or months can be | |||
| 7291 | # between 1 and 12). The absolute value of $N determines the range and | |||
| 7292 | # the sign of $N determines whether the range is 0 to N-1 (if N>0) or | |||
| 7293 | # 1 to N (N<0). The remainder (as modulo N) is added to $rem. | |||
| 7294 | # Example: | |||
| 7295 | # To add 2 hours together (with the excess returned in days) use: | |||
| 7296 | # _ModuloAddition(60,$s1,\$s,\$day); | |||
| 7297 | sub _ModuloAddition { | |||
| 7298 | my($N,$add,$val,$rem)=@_; | |||
| 7299 | return if ($N==0); | |||
| 7300 | $$val+=$add; | |||
| 7301 | if ($N<0) { | |||
| 7302 | # 1 to N | |||
| 7303 | $N = -$N; | |||
| 7304 | if ($$val>$N) { | |||
| 7305 | $$rem+= int(($$val-1)/$N); | |||
| 7306 | $$val = ($$val-1)%$N +1; | |||
| 7307 | } elsif ($$val<1) { | |||
| 7308 | $$rem-= int(-$$val/$N)+1; | |||
| 7309 | $$val = $N-(-$$val % $N); | |||
| 7310 | } | |||
| 7311 | ||||
| 7312 | } else { | |||
| 7313 | # 0 to N-1 | |||
| 7314 | if ($$val>($N-1)) { | |||
| 7315 | $$rem+= int($$val/$N); | |||
| 7316 | $$val = $$val%$N; | |||
| 7317 | } elsif ($$val<0) { | |||
| 7318 | $$rem-= int(-($$val+1)/$N)+1; | |||
| 7319 | $$val = ($N-1)-(-($$val+1)%$N); | |||
| 7320 | } | |||
| 7321 | } | |||
| 7322 | } | |||
| 7323 | ||||
| 7324 | # $Flag=_IsInt($String [,$low, $high]); | |||
| 7325 | # Returns 1 if $String is a valid integer, 0 otherwise. If $low is | |||
| 7326 | # entered, $String must be >= $low. If $high is entered, $String must | |||
| 7327 | # be <= $high. It is valid to check only one of the bounds. | |||
| 7328 | sub _IsInt { | |||
| 7329 | my($N,$low,$high)=@_; | |||
| 7330 | return 0 if (! defined $N or | |||
| 7331 | $N !~ /^\s*[-+]?\d+\s*$/ or | |||
| 7332 | defined $low && $N<$low or | |||
| 7333 | defined $high && $N>$high); | |||
| 7334 | return 1; | |||
| 7335 | } | |||
| 7336 | ||||
| 7337 | # $File=_CleanFile($file); | |||
| 7338 | # This cleans up a path to remove the following things: | |||
| 7339 | # double slash /a//b -> /a/b | |||
| 7340 | # trailing dot /a/. -> /a | |||
| 7341 | # leading dot ./a -> a | |||
| 7342 | # trailing slash a/ -> a | |||
| 7343 | sub _CleanFile { | |||
| 7344 | my($file)=@_; | |||
| 7345 | $file =~ s/\s*$//; | |||
| 7346 | $file =~ s/^\s*//; | |||
| 7347 | $file =~ s|//+|/|g; # multiple slash | |||
| 7348 | $file =~ s|/\.$|/|; # trailing /. (leaves trailing slash) | |||
| 7349 | $file =~ s|^\./|| # leading ./ | |||
| 7350 | if ($file ne "./"); | |||
| 7351 | $file =~ s|/$|| # trailing slash | |||
| 7352 | if ($file ne "/"); | |||
| 7353 | return $file; | |||
| 7354 | } | |||
| 7355 | ||||
| 7356 | # $File=_ExpandTilde($file); | |||
| 7357 | # This checks to see if a "~" appears as the first character in a path. | |||
| 7358 | # If it does, the "~" expansion is interpreted (if possible) and the full | |||
| 7359 | # path is returned. If a "~" expansion is used but cannot be | |||
| 7360 | # interpreted, an empty string is returned. | |||
| 7361 | # | |||
| 7362 | # This is Windows/Mac friendly. | |||
| 7363 | # This is efficient. | |||
| 7364 | sub _ExpandTilde { | |||
| 7365 | my($file)=shift; | |||
| 7366 | my($user,$home)=(); | |||
| 7367 | # ~aaa/bbb= ~ aaa /bbb | |||
| 7368 | if ($file =~ s|^~([^/]*)||) { | |||
| 7369 | $user=$1; | |||
| 7370 | # Single user operating systems (Mac, MSWindows) don't have the getpwnam | |||
| 7371 | # and getpwuid routines defined. Try to catch various different ways | |||
| 7372 | # of knowing we are on one of these systems: | |||
| 7373 | return "" if ($OS eq "Windows" or | |||
| 7374 | $OS eq "Mac" or | |||
| 7375 | $OS eq "Netware" or | |||
| 7376 | $OS eq "MPE"); | |||
| 7377 | $user="" if (! defined $user); | |||
| 7378 | ||||
| 7379 | if ($user) { | |||
| 7380 | $home= (getpwnam($user))[7]; | |||
| 7381 | } else { | |||
| 7382 | $home= (getpwuid($<))[7]; | |||
| 7383 | } | |||
| 7384 | $home = VMS::Filespec::unixpath($home) if ($OS eq "VMS"); | |||
| 7385 | return "" if (! $home); | |||
| 7386 | $file="$home/$file"; | |||
| 7387 | } | |||
| 7388 | $file; | |||
| 7389 | } | |||
| 7390 | ||||
| 7391 | # $File=_FullFilePath($file); | |||
| 7392 | # Returns the full or relative path to $file (expanding "~" if necessary). | |||
| 7393 | # Returns an empty string if a "~" expansion cannot be interpreted. The | |||
| 7394 | # path does not need to exist. _CleanFile is called. | |||
| 7395 | sub _FullFilePath { | |||
| 7396 | my($file)=shift; | |||
| 7397 | my($rootpat) = '^/'; #default pattern to match absolute path | |||
| 7398 | $rootpat = '^(\\|/|([A-Za-z]:[\\/]))' if ($OS eq 'Windows'); | |||
| 7399 | $file=_ExpandTilde($file); | |||
| 7400 | return "" if (! $file); | |||
| 7401 | return _CleanFile($file); | |||
| 7402 | } | |||
| 7403 | ||||
| 7404 | # $Flag=_CheckFilePath($file [,$mode]); | |||
| 7405 | # Checks to see if $file exists, to see what type it is, and whether | |||
| 7406 | # the script can access it. If it exists and has the correct mode, 1 | |||
| 7407 | # is returned. | |||
| 7408 | # | |||
| 7409 | # $mode is a string which may contain any of the valid file test operator | |||
| 7410 | # characters except t, M, A, C. The appropriate test is run for each | |||
| 7411 | # character. For example, if $mode is "re" the -r and -e tests are both | |||
| 7412 | # run. | |||
| 7413 | # | |||
| 7414 | # An empty string is returned if the file doesn't exist. A 0 is returned | |||
| 7415 | # if the file exists but any test fails. | |||
| 7416 | # | |||
| 7417 | # All characters in $mode which do not correspond to valid tests are | |||
| 7418 | # ignored. | |||
| 7419 | sub _CheckFilePath { | |||
| 7420 | my($file,$mode)=@_; | |||
| 7421 | my($test)=(); | |||
| 7422 | $file=_FullFilePath($file); | |||
| 7423 | $mode = "" if (! defined $mode); | |||
| 7424 | ||||
| 7425 | # Run tests | |||
| 7426 | return 0 if (! defined $file or ! $file); | |||
| 7427 | return 0 if (( ! -e $file) or | |||
| 7428 | ($mode =~ /r/ && ! -r $file) or | |||
| 7429 | ($mode =~ /w/ && ! -w $file) or | |||
| 7430 | ($mode =~ /x/ && ! -x $file) or | |||
| 7431 | ($mode =~ /R/ && ! -R $file) or | |||
| 7432 | ($mode =~ /W/ && ! -W $file) or | |||
| 7433 | ($mode =~ /X/ && ! -X $file) or | |||
| 7434 | ($mode =~ /o/ && ! -o $file) or | |||
| 7435 | ($mode =~ /O/ && ! -O $file) or | |||
| 7436 | ($mode =~ /z/ && ! -z $file) or | |||
| 7437 | ($mode =~ /s/ && ! -s $file) or | |||
| 7438 | ($mode =~ /f/ && ! -f $file) or | |||
| 7439 | ($mode =~ /d/ && ! -d $file) or | |||
| 7440 | ($mode =~ /l/ && ! -l $file) or | |||
| 7441 | ($mode =~ /s/ && ! -s $file) or | |||
| 7442 | ($mode =~ /p/ && ! -p $file) or | |||
| 7443 | ($mode =~ /b/ && ! -b $file) or | |||
| 7444 | ($mode =~ /c/ && ! -c $file) or | |||
| 7445 | ($mode =~ /u/ && ! -u $file) or | |||
| 7446 | ($mode =~ /g/ && ! -g $file) or | |||
| 7447 | ($mode =~ /k/ && ! -k $file) or | |||
| 7448 | ($mode =~ /T/ && ! -T $file) or | |||
| 7449 | ($mode =~ /B/ && ! -B $file)); | |||
| 7450 | return 1; | |||
| 7451 | } | |||
| 7452 | #&& | |||
| 7453 | ||||
| 7454 | # $Path=_FixPath($path [,$full] [,$mode] [,$error]); | |||
| 7455 | # Makes sure that every directory in $path (a colon separated list of | |||
| 7456 | # directories) appears as a full path or relative path. All "~" | |||
| 7457 | # expansions are removed. All trailing slashes are removed also. If | |||
| 7458 | # $full is non-nil, relative paths are expanded to full paths as well. | |||
| 7459 | # | |||
| 7460 | # If $mode is given, it may be either "e", "r", or "w". In this case, | |||
| 7461 | # additional checking is done to each directory. If $mode is "e", it | |||
| 7462 | # need ony exist to pass the check. If $mode is "r", it must have have | |||
| 7463 | # read and execute permission. If $mode is "w", it must have read, | |||
| 7464 | # write, and execute permission. | |||
| 7465 | # | |||
| 7466 | # The value of $error determines what happens if the directory does not | |||
| 7467 | # pass the test. If it is non-nil, if any directory does not pass the | |||
| 7468 | # test, the subroutine returns the empty string. Otherwise, it is simply | |||
| 7469 | # removed from $path. | |||
| 7470 | # | |||
| 7471 | # The corrected path is returned. | |||
| 7472 | sub _FixPath { | |||
| 7473 | my($path,$full,$mode,$err)=@_; | |||
| 7474 | local($_)=""; | |||
| 7475 | my(@dir)=split(/$Cnf{"PathSep"}/,$path); | |||
| 7476 | $full=0 if (! defined $full); | |||
| 7477 | $mode="" if (! defined $mode); | |||
| 7478 | $err=0 if (! defined $err); | |||
| 7479 | $path=""; | |||
| 7480 | if ($mode eq "e") { | |||
| 7481 | $mode="de"; | |||
| 7482 | } elsif ($mode eq "r") { | |||
| 7483 | $mode="derx"; | |||
| 7484 | } elsif ($mode eq "w") { | |||
| 7485 | $mode="derwx"; | |||
| 7486 | } | |||
| 7487 | ||||
| 7488 | foreach (@dir) { | |||
| 7489 | ||||
| 7490 | # Expand path | |||
| 7491 | if ($full) { | |||
| 7492 | $_=_FullFilePath($_); | |||
| 7493 | } else { | |||
| 7494 | $_=_ExpandTilde($_); | |||
| 7495 | } | |||
| 7496 | if (! $_) { | |||
| 7497 | return "" if ($err); | |||
| 7498 | next; | |||
| 7499 | } | |||
| 7500 | ||||
| 7501 | # Check mode | |||
| 7502 | if (! $mode or _CheckFilePath($_,$mode)) { | |||
| 7503 | $path .= $Cnf{"PathSep"} . $_; | |||
| 7504 | } else { | |||
| 7505 | return "" if ($err); | |||
| 7506 | } | |||
| 7507 | } | |||
| 7508 | $path =~ s/^$Cnf{"PathSep"}//; | |||
| 7509 | return $path; | |||
| 7510 | } | |||
| 7511 | #&& | |||
| 7512 | ||||
| 7513 | # $File=_SearchPath($file,$path [,$mode] [,@suffixes]); | |||
| 7514 | # Searches through directories in $path for a file named $file. The | |||
| 7515 | # full path is returned if one is found, or an empty string otherwise. | |||
| 7516 | # The file may exist with one of the @suffixes. The mode is checked | |||
| 7517 | # similar to _CheckFilePath. | |||
| 7518 | # | |||
| 7519 | # The first full path that matches the name and mode is returned. If none | |||
| 7520 | # is found, an empty string is returned. | |||
| 7521 | sub _SearchPath { | |||
| 7522 | my($file,$path,$mode,@suff)=@_; | |||
| 7523 | my($f,$s,$d,@dir,$fs)=(); | |||
| 7524 | $path=_FixPath($path,1,"r"); | |||
| 7525 | @dir=split(/$Cnf{"PathSep"}/,$path); | |||
| 7526 | foreach $d (@dir) { | |||
| 7527 | $f="$d/$file"; | |||
| 7528 | $f=~ s|//|/|g; | |||
| 7529 | return $f if (_CheckFilePath($f,$mode)); | |||
| 7530 | foreach $s (@suff) { | |||
| 7531 | $fs="$f.$s"; | |||
| 7532 | return $fs if (_CheckFilePath($fs,$mode)); | |||
| 7533 | } | |||
| 7534 | } | |||
| 7535 | return ""; | |||
| 7536 | } | |||
| 7537 | ||||
| 7538 | # @list=_ReturnList($str); | |||
| 7539 | # This takes a string which should be a comma separated list of integers | |||
| 7540 | # or ranges (5-7). It returns a sorted list of all integers referred to | |||
| 7541 | # by the string, or () if there is an invalid element. | |||
| 7542 | # | |||
| 7543 | # Negative integers are also handled. "-2--1" is equivalent to "-2,-1". | |||
| 7544 | sub _ReturnList { | |||
| 7545 | my($str)=@_; | |||
| 7546 | my(@ret,@str,$from,$to,$tmp)=(); | |||
| 7547 | @str=split(/,/,$str); | |||
| 7548 | foreach $str (@str) { | |||
| 7549 | if ($str =~ /^[-+]?\d+$/) { | |||
| 7550 | push(@ret,$str); | |||
| 7551 | } elsif ($str =~ /^([-+]?\d+)-([-+]?\d+)$/) { | |||
| 7552 | ($from,$to)=($1,$2); | |||
| 7553 | if ($from>$to) { | |||
| 7554 | $tmp=$from; | |||
| 7555 | $from=$to; | |||
| 7556 | $to=$tmp; | |||
| 7557 | } | |||
| 7558 | push(@ret,$from..$to); | |||
| 7559 | } else { | |||
| 7560 | return (); | |||
| 7561 | } | |||
| 7562 | } | |||
| 7563 | @ret; | |||
| 7564 | } | |||
| 7565 | ||||
| 7566 | 1 | 71µs | 71µs | 1; |
| 7567 | # Local Variables: | |||
| 7568 | # mode: cperl | |||
| 7569 | # indent-tabs-mode: nil | |||
| 7570 | # cperl-indent-level: 3 | |||
| 7571 | # cperl-continued-statement-offset: 2 | |||
| 7572 | # cperl-continued-brace-offset: 0 | |||
| 7573 | # cperl-brace-offset: 0 | |||
| 7574 | # cperl-brace-imaginary-offset: 0 | |||
| 7575 | # cperl-label-offset: -2 | |||
| 7576 | # End: |