If you're seeing
100's where you previously had a two-digit year, then your script definitely
has a "y2k problem." The first thing you should do
is search for any lines containing either "localtime" or
"gmtime" which are almost always part of these array statements
(often found in subroutines dealing with dates or
times):($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
or
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
Note the occurrences of the sixth element, "$year" elsewhere in
your script! Many script authors used "$year" without
any further logic as being equivalent to a two-digit representation of
the year. They took advantage of the fact that the results were conveniently
the same for every year between 1900 and 1999. But we're no longer
living in the 20th century! For the next nine years, you
can have the correct two-digit year by adding the following correction
somewhere after the array statements for "localtime"
or "gmtime" (as shown above) and before "$year"
is used as a two-digit year in your
program: $ydif = $year - 100;
$year = "0$ydif";
If you require a more extensive correction (one that outputs the correct
digits for years previous to 2000 and after 2009), then
please send me an email.
An alternative for displaying the present
date with a two-digit year is to use the POSIX module's
strftime function. Here's an example:
use POSIX;
which would produce a display similar to this: Thu, 17 Feb 00.
$datime = POSIX::strftime("%a, %d %b %y", localtime);
print "$datime";
The following material is either
taken directly from the Perl Documentation (as noted) or based upon it, and
should be quite helpful in dealing with all time and date function
problems in general:
From
PerlFAQ 4:
----------------- Does Perl have a year 2000 problem? Is Perl Y2K compliant?
Short answer: No, Perl does not have a Year 2000 problem. Yes,
Perl is Y2K compliant (whatever that means). The programmers
you've hired to use it, however, probably are not.
Long answer: The question belies a true understanding of the
issue. Perl is just as Y2K compliant as your pencil--no more,
and no less. Can you use your pencil to write a non-Y2K-
compliant memo? Of course you can. Is that the pencil's
fault? Of course it isn't.
The date and time functions supplied with perl (gmtime and
localtime) supply adequate information to determine the year
well beyond 2000 (it won't be until 2038 that trouble strikes
for 32-bit machines). The year returned by these functions
when used in an array context is the year minus 1900. For
years between 1910 and 1999 this *happens* to be a 2-digit
decimal number. To avoid the year 2000 problem simply do not
treat the year as a 2-digit number. It isn't.
When gmtime() and localtime() are used in scalar context they
return a timestamp string that contains a fully-expanded year.
For example, `$timestamp = gmtime(1005613200)' sets
$timestamp to "Tue Nov 13 01:00:00 2001". There's no year
2000 problem here.
That doesn't mean that Perl can't be used to create non-Y2K
compliant programs. It can. But so can your pencil. It's
the fault of the user, not the language.
---------------------------------------------------------------
Data: Dates
How do I find the week-of-the-year/day-of-the-year?
The day of the year is in the array returned by localtime():
$day_of_year = (localtime(time()))[7];
or more legibly (in perl version 5.004 or higher):
use Time::localtime;
$day_of_year = localtime(time())->yday;
The Date::Calc module from CPAN has a lot of date calculation
functions, including day of the year, week of the year, and so
on. Note that not all businesses consider ``week 1'' to be the
same; for example, American businesses often consider the first
week with a Monday in it to be Work Week #1, despite ISO 8601,
which considers WW1 to be the first week with a Thursday in it.
How can I compare two dates and find the difference?
If you're storing your dates as epoch seconds then simply
subtract one from the other. If you've got a structured date
(distinct year, day, month, hour, minute, second values) then
use one of the Date::Manip and Date::Calc modules from CPAN.
How can I take a string and turn it into epoch seconds?
If it's a regular enough string that it always has the same
format, you can split it up and pass the parts to `timelocal' in
the standard Time::Local module. Otherwise, you should look into
the Date::Calc and Date::Manip modules from CPAN.
How can I find the Julian Day?
Neither Date::Manip nor Date::Calc deal with Julian days.
Instead, there is an example of Julian date calculation that
should help you in Time::JulianDay (part of the Time-modules
bundle) which can be found at:
http://www.perl.com/CPAN/modules/by-module/Time/.
How do I find yesterday's date?
The `time()' function returns the current time in seconds since
the epoch. Take one day off that:
$yesterday = time() - ( 24 * 60 * 60 );
Then you can pass this to `localtime()' and get the individual
year, month, day, hour, minute, seconds values.
From
Perlfunc.pod or the POSIX.pod:
--------------------------------------
time
Returns the number of non-leap seconds since whatever time
the system considers to be the epoch (that's 00:00:00,
January 1, 1904 for MacOS, and 00:00:00 UTC, January 1,
1970 for most other systems). Suitable for feeding to
`gmtime()' and `localtime()'.
------------------
localtime EXPR
Converts a time as returned by the time function to a
9-element array with the time analyzed for the local
time zone. Typically used as follows:
# 0 1 2 3 4 5 6 7 8
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
All array elements are numeric, and come straight out of
a struct tm. In particular this means that `$mon' has the
range `0..11' and `$wday' has the range `0..6' with Sunday
as day `0'. Also, `$year' is the number of years since
1900, that is, `$year' is `123' in year 2023, and *not*
simply the last two digits of the year. If you assume it
is, then you create non-Y2K-compliant programs--and you
wouldn't want to do that, would you?
If EXPR is omitted, the function uses the current time
(`localtime(time)').
In a scalar context, localtime returns the ctime(3) value.
For example, printing out the scalar variable $now from
$now = localtime; has the form: "Wed Oct 12 14:54:34 1999"
You can also print it out by using a statement like this:
print "\n\n The time is: ",scalar(localtime),"\n";
This scalar value is a Perl builtin, not locale dependent;
see the perllocale manpage. Read about the `Time::Local'
module, and the strftime(3) and mktime(3) functions which
are available via the POSIX module. To get somewhat similar
but locale dependent date strings, set up your locale
environment variables appropriately (please see the
perllocale manpage) and try for example:
use POSIX qw(strftime);
$now_string = strftime("%a %b %d %H:%M:%S %Y", localtime);
print "\n\n Date/Time are now: $now_string";
The output should be similar to:
Date/Time are now: Thu Feb 17 11:42:07 2000.
The parentheses, ( ), after strftime above are optional.
Note that the `%a' and `%b', the "short forms" for the day
of the week and the month of the year, may not necessarily
be three characters wide. (Also, the original documentation
incorrectly had an "%e" instead of the "%d" shown above.)
------------------
gmtime EXPR
Converts a time as returned by the time function to a
9-element array with the time localized for the standard
Greenwich time zone. Typically used as follows:
# 0 1 2 3 4 5 6 7 8
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
gmtime(time);
[ Same comments follow as found in "localtime EXPR" above! ]
------------------
NAME
Time::Local - efficiently compute time from local and GMT time
SYNOPSIS
$time = timelocal($sec,$min,$hours,$mday,$mon,$year);
$time = timegm($sec,$min,$hours,$mday,$mon,$year);
DESCRIPTION
These routines are quite efficient and yet are always guaranteed
to agree with localtime() and gmtime(), the most notable points
being that year is year-1900 and month is 0..11. We manage this
by caching the start times of any months we've seen before. If
we know the start time of the month, we can always calculate any
time within the month. The start times themselves are guessed by
successive approximation starting at the current time, since
most dates seen in practice are close to the current date.
Unlike algorithms that do a binary search (calling gmtime once
for each bit of the time value, resulting in 32 calls), this
algorithm calls it at most 6 times, and usually only once or
twice. If you hit the month cache, of course, it doesn't call it
at all.
timelocal is implemented using the same cache. We just assume
that we're translating a GMT time, and then fudge it when we're
done for the timezone and daylight savings arguments. The
timezone is determined by examining the result of localtime(0)
when the package is initialized. The daylight savings offset is
currently assumed to be one hour.
Both routines return -1 if the integer limit is hit. I.e., for
dates after the 1st of January, 2038 on most machines.
Note: Use the variable name $hour not $hours (as given in the
original documentation) in order to be consistent with the
variable name $hour in the localtime() and gmtime() functions.
-------------------
NAME
Time::localtime - by-name interface to Perl's built-in
localtime() function
SYNOPSIS
use Time::localtime;
printf "Year is %d\n", localtime->year() + 1900;
$now = ctime(); or try this at the Command-Line prompt:
C:\Perl\bin>perl -e "use Time::localtime; print scalar(ctime());"
which displayed: Thu Feb 17 14:06:00 2000 for me.
use Time::localtime;
use File::stat;
[ $file = "drive:\\pathway\\anyvalidfilename"; ] or for example:
$file = "C:/pathway/test.pl"; and then I used
$date_string = ctime(stat($file)->mtime); and
print "$file was last modified at: $date_string"; to display:
test.pl was last modified at: Thu Jan 27 08:47:36 2000
DESCRIPTION
This module's default exports override the core localtime()
function, replacing it with a version that returns "Time::tm"
objects. This object has methods that return the similarly named
structure field name from the C's tm structure from time.h;
namely sec, min, hour, mday, mon, year, wday, yday, and isdst.
You may also import all the structure fields directly into your
namespace as regular variables using the :FIELDS import tag.
(Note that this still overrides your core functions.) Access
these fields as variables named with a preceding `tm_' in front
[of] their method names. Thus, `$tm_obj->mday()' corresponds to
$tm_mday if you import the fields.
The ctime() function provides a way of getting at the scalar
sense of the original CORE::localtime() function.
To access this functionality without the core overrides, pass
the `use' an empty import list, and then access function[s]
with their full[y] qualified names. On the other hand, the
built-ins are still available via the `CORE::' pseudo-package.
NOTE
While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.
-------------------
NAME
POSIX - Perl interface to IEEE Std 1003.1
[ Note: This is just a fraction of the Perl
Documentation on POSIX functions! ]
SYNOPSIS
use POSIX;
use POSIX qw(setsid);
DESCRIPTION [ Merely a brief summary here before describing
some of the POSIX time/date functions! ]
The POSIX module permits you to access all (or nearly all) the
standard POSIX 1003.1 identifiers. Many of these identifiers
have been given Perl-ish interfaces. All functions are only
exported if you ask for them explicitly. Most likely people
will prefer to use the fully-qualified function names.
ctime This is identical to the C function `ctime()'.
mktime Convert date/time info to a calendar time.
Synopsis:
mktime(sec, min, hour, mday, mon, year, wday=0, yday=0, isdst=0)
The month (`mon'), weekday (`wday'), and yearday (`yday') begin
at zero. I.e., January is 0, not 1; Sunday is 0, not 1; January
1st is 0, not 1. The year (`year') is given in years since 1900.
I.e., The year 1995 is 95, but the year 2001 is 101. Consult
your system's `mktime()' manpage for details about these and the
other arguments. Use this before calling strftime in a program.
Returns `undef' on failure.
Calendar time for December 23, 1999, at 10:30AM may be found
using:
use POSIX qw(mktime);
$time_t = mktime ( 0, 30, 10, 23, 11, 99 ); and
print "\n\n \$time_t = $time_t \n"; which will display:
$time_t = 945973800 on your screen.
The process can then be reversed to find the weekday too using:
print "\n\n Date = ", POSIX::ctime($time_t),"\n"; which displays:
Date = Thu Dec 23 10:30:00 1999
If you try using this line at the Command prompt:
C:\>perl -e "use POSIX; print scalar(POSIX::mktime(0,0,0,1,0,100));"
you'll find that the beginning of the new year 2000 was at time:
C:\>946713600 or Sat Jan 01 00:00:00 2000
strftime Convert date and time information to string.
Returns the string.
Synopsis:
strftime(format, sec, min, hour, mday, mon, year, wday = -1,
yday = -1, isdst = -1)
The month (`mon'), weekday (`wday'), and yearday (`yday') begin
at zero. I.e., January is 0, not 1; Sunday is 0, not 1; January
1st is 0, not 1. The year (`year') is given in years since 1900.
I.e., the year 1995 is 95; the year 2001 is 101. Consult your
system's `strftime()' manpage for details about these and other
arguments. The given arguments are made consistent by calling
`mktime()' before calling your system's `strftime()' function.
Most of the time you can exclude the elements with a "-1" even
if you wish to display the day of the week; both strftime and
mktime() will calculate that for you given the day of the month,
the month and the year. We must, however, include some kind of
data for the first three elements (sec, min, hour) even though
you may not be displaying the time (just use zeros in this case).
format may include either A or a, B or b, d, Y or y, H, M or S;
(the time normally being displayed as %H:%M:%S) in any order or
combination. For example:
use POSIX;
$str = POSIX::strftime("%A, %B %d, %Y", 0, 0, 0, 12, 2, 101);
print " $str\n"; will display:
Monday, March 12, 2001