TimeDate-2.35 000755 000765 000024 0 15157412057 13062 5 ustar 00nicolas staff 000000 000000 README 100644 000765 000024 554 15157412057 14007 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 This archive contains the distribution TimeDate,
version 2.35:
Date and time formatting subroutines
This software is copyright (c) 2020 by Graham Barr.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
This README file was generated by Dist::Zilla::Plugin::Readme v6.033.
LICENSE 100644 000765 000024 46276 15157412057 14207 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 This software is copyright (c) 2020 by Graham Barr.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
Terms of the Perl programming language system itself
a) the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any
later version, or
b) the "Artistic License"
--- The GNU General Public License, Version 1, February 1989 ---
This software is Copyright (c) 2020 by Graham Barr.
This is free software, licensed under:
The GNU General Public License, Version 1, February 1989
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The license agreements of most software companies try to keep users
at the mercy of those companies. By contrast, our General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. The
General Public License applies to the Free Software Foundation's
software and to any other program whose authors commit to using it.
You can use it for your programs, too.
When we speak of free software, we are referring to freedom, not
price. Specifically, the General Public License is designed to make
sure that you have the freedom to give away or sell copies of free
software, that you receive source code or can get it if you want it,
that you can change the software or use pieces of it in new free
programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of a such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must tell them their rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any program or other work which
contains a notice placed by the copyright holder saying it may be
distributed under the terms of this General Public License. The
"Program", below, refers to any such program or work, and a "work based
on the Program" means either the Program or any work containing the
Program or a portion of it, either verbatim or with modifications. Each
licensee is addressed as "you".
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this
General Public License and to the absence of any warranty; and give any
other recipients of the Program a copy of this General Public License
along with the Program. You may charge a fee for the physical act of
transferring a copy.
2. You may modify your copy or copies of the Program or any portion of
it, and copy and distribute such modifications under the terms of Paragraph
1 above, provided that you also do the following:
a) cause the modified files to carry prominent notices stating that
you changed the files and the date of any change; and
b) cause the whole of any work that you distribute or publish, that
in whole or in part contains the Program or any part thereof, either
with or without modifications, to be licensed at no charge to all
third parties under the terms of this General Public License (except
that you may choose to grant warranty protection to some or all
third parties, at your option).
c) If the modified program normally reads commands interactively when
run, you must cause it, when started running for such interactive use
in the simplest and most usual way, to print or display an
announcement including an appropriate copyright notice and a notice
that there is no warranty (or else, saying that you provide a
warranty) and that users may redistribute the program under these
conditions, and telling the user how to view a copy of this General
Public License.
d) You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
Mere aggregation of another independent work with the Program (or its
derivative) on a volume of a storage or distribution medium does not bring
the other work under the scope of these terms.
3. You may copy and distribute the Program (or a portion or derivative of
it, under Paragraph 2) in object code or executable form under the terms of
Paragraphs 1 and 2 above provided that you also do one of the following:
a) accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of
Paragraphs 1 and 2 above; or,
b) accompany it with a written offer, valid for at least three
years, to give any third party free (except for a nominal charge
for the cost of distribution) a complete machine-readable copy of the
corresponding source code, to be distributed under the terms of
Paragraphs 1 and 2 above; or,
c) accompany it with the information you received as to where the
corresponding source code may be obtained. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form alone.)
Source code for a work means the preferred form of the work for making
modifications to it. For an executable file, complete source code means
all the source code for all modules it contains; but, as a special
exception, it need not include source code for modules which are standard
libraries that accompany the operating system on which the executable
file runs, or for standard header files or definitions files that
accompany that operating system.
4. You may not copy, modify, sublicense, distribute or transfer the
Program except as expressly provided under this General Public License.
Any attempt otherwise to copy, modify, sublicense, distribute or transfer
the Program is void, and will automatically terminate your rights to use
the Program under this License. However, parties who have received
copies, or rights to use copies, from you under this General Public
License will not have their licenses terminated so long as such parties
remain in full compliance.
5. By copying, distributing or modifying the Program (or any work based
on the Program) you indicate your acceptance of this license to do so,
and all its terms and conditions.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these
terms and conditions. You may not impose any further restrictions on the
recipients' exercise of the rights granted herein.
7. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of the license which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
the license, you may choose any version ever published by the Free Software
Foundation.
8. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to humanity, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.
To do so, attach the following notices to the program. It is safest to
attach them to the start of each source file to most effectively convey
the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
Copyright (C) 19yy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see .
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19xx name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License. Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items--whatever suits your
program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
program `Gnomovision' (a program to direct compilers to make passes
at assemblers) written by James Hacker.
, 1 April 1989
Moe Ghoul, President of Vice
That's all there is to it!
--- The Perl Artistic License 1.0 ---
This software is Copyright (c) 2020 by Graham Barr.
This is free software, licensed under:
The Perl Artistic License 1.0
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
Changes 100644 000765 000024 35456 15157412057 14473 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 Revision history for TimeDate distribution.
2.35 2026-03-20 21:44:45-06:00 America/Denver
2.34_03 2026-03-18 22:12:43-06:00 America/Denver (TRIAL RELEASE)
* test: document and pin RT#84075/GH#12 fix in regression suite
* fix: add NST, NFT, and NDT (Newfoundland) timezone support
* fix: add ICT and PHT timezone support
* fix: restore rebase regressions and clarify first-century limitation
* fix: normalize two-digit years in str2time to avoid Time::Local windowing mismatch
* fix: use standard 2-letter German weekday abbreviations
* fix: detect timegm/timelocal overflow for far-future dates (RT#88777)
* test: add regression tests for RT#88777 (negative epoch for far-future dates)
* fix: use stored epoch in format_Z/format_z to fix DST fall-back timezone name
* fix: document MSK timezone history and add regression test (RT#98949)
* fix: strftime %s with timezone now returns correct epoch (RT#52387)
* test: add POD validity regression test for RT#53557
* fix: include day in year-inference for dates without an explicit year
* fix: document MSK timezone history and add regression test (RT#81350)
* ci: install Pod::Checker via cpm in Linux CI
* docs: add SECURITY.md with vulnerability reporting policy
* test: add regression tests for RT#57800 / GH#3 (numeric m/d/yyyy pre-1970 dates)
* fix: normalize year offset for dates before 1901 in strptime (RT#106105)
* fix: reject timezone-only inputs in strptime (RT#70650)
* test: add failing tests for RT#70650 (ludicrous date parsing)
* fix: prevent negative month from strptime for 6-digit inputs like '199001'
* test: add Portuguese format and round-trip tests from PR #61
* fix: treat number > 31 after month name as year, not day (GH#2)
* fix: translate timezone abbreviations (%Z) in language-specific formatting
* fix: tz_name() offset in seconds was treated as minutes (RT#59298)
* docs: fix ISO-8601 example date in Date::Parse POD (issue #6)
* feat: add optional LANGUAGE parameter to time2str()
* feat: allow str2time() to accept a custom reference epoch (RT#64789)
* docs: clarify strptime() return format for ISO 8601 dates (issue #44)
* feat: add Portuguese language module
* fix: prefer CEST over MEST as canonical Central European Summer Time name
* fix: add ICT and PHT timezone abbreviations to Time::Zone (RT#123247)
* fix: standardize Greek.pm to use native Unicode instead of \x{} escapes
* test: add regression test for RT#105031 / GH#17 (1965-12-31 maps to 2065)
* fix: declare Carp as runtime prerequisite in Makefile.PL
* fix: infer current year for future months when no year given (RT#92611)
* test: add regression tests for RT#53413 (4-digit year mangling)
* fix: handle leap day in year-only date parsing test
* fix: support IANA timezone names in tz2zone and tz_offset (RT#76968)
* fix: preserve comma as ISO 8601 decimal separator in strptime
* fix: add French day ordinal suffix in format_o
* fix: make tz_name tests deterministic across DST transitions
2.34 2026-02-27 17:00:48-07:00 America/Denver
* doc: Increase POD coverage
* refactor: extract _build_lookups helper, remove hash-building duplication
* fix: correct language data bugs and minor code review fixes
* Fixup utf8 and add tests
* Use Dist::Zilla for the distro
* rebase: apply review feedback on #52
* fix: uncomment Indian Standard timezone (IST)
* feat: support boost C++ timestamp format (%Y-%b-%d %H:%M:%S.%f)
* fix: correct typos across documentation and comments
* stop using use vars
* rebase: apply review feedback on #49
* Remove limitation from Date::Parse
* Create Arabic.pm
2.33 2020-05-19 11:34:00-06:00 America/Denver
* Remove PAX Headers in tarball using GNU tar
2.32 2020-03-04 14:41:00-07:00 America/Denver
* Fix t/date.t to run on leap years [arc]
2.31 2020-01-16 14:00:00-07:00 America/Denver
* Fix year 2020 bug from t/getdate.t [Prajith]
* Fix warnings from t/date.t
* Fix pod issue in lib/Date/Parse.pm
* Fix for French language using English day suffixes in %o [mitchjacksontech]
* RT#84075: Fix Date::Parse::str2time century issue. [perlpilot]
* Adds Occitan language. [Quenty31]
* Migrate GitHub repo and bugtracker to atoomic/perl-TimeDate
2.30 2013-02-18 13:31:03-06:00 America/Chicago
* Syncing distribution version number with Date::Parse, not functional changes
1.20 2009-12-12 06:38:14-06:00 America/Chicago
* Typo => s/timezome/timezone/ [yanick]
* RT#52387 Fix %s formating to use timelocal when no timezone is given
* RT#51664 fix str2time('16 Oct 09') to not give a negative result
1.19 2009-09-25 13:59:41-05:00 America/Chicago
* Replace Date::Language::Hungarian with version from CPAN by Lee Goddard
1.18 2009-09-24 17:43:28-05:00 America/Chicago
* RT#49963 Skip pre 1970 date tests on Win32
* Added Date::Language::Hungarian (Konrad Lorinczi)
1.17 2009-09-19 10:56:12-05:00 America/Chicago
Bugfixes
* RT#45067: Date::Format with %z gives wrong results for half-hour timezones (Ernesto Hern?dez-Novich)
* RT#48164: Date::Parse unable to set seconds correctly
* RT#17396: Parse error for french date with 'mars' (march) as month
Documentation
* Fixed documentation for %e in Date::Format
* Update documentation to remove Date::Format->language
Enhancements
* Add support for dates like Jul-13-1999 (Brett Warden)
* Added Icelandic language (Tomas Edwardsson)
* Added Romanian language (Doru Petrescu)
* Added Russian language (Denis Poznyakov & Danil Pismenny)
* Added Turkish language (Burak Gursoy)
* Added Spanish language (Adrian Mugnolo)
* Added Chinese language (Kang-min Liu)
* Support parsing dates like 2002-02-26-10:37:21.141 as used by lpd
* Support Z timezone when only the time is specified
* Added METDST to Time::Zone
* Added AKST/AKDT to Time::Zone
Changes prior to 1.17
Change 814 on 2003/06/03 by (Graham Barr)
Date::Parse
- Time::Local in 5.8 does not support fractional seconds
Change 813 on 2003/06/02 by (Graham Barr)
Release 1.15
Change 812 on 2003/06/02 by (Graham Barr)
Fix comments about Language implementation in Date::Parse
(patch from Christian Hammers)
Change 811 on 2003/06/02 by (Graham Barr)
Fix short name for 'maart' to be 'mrt' as suggested by Frank Maas
Change 810 on 2003/06/02 by (Graham Barr)
Add %G format for GPS week (patch from Eric Richardson)
Change 809 on 2003/06/02 by (Graham Barr)
Language updates from Daniel Yacob
Change 808 on 2003/06/02 by (Graham Barr)
str2time("") should return undef
Change 807 on 2003/06/02 by (Graham Barr)
Added Swedish and Finnish languages from Matthew Musgrove
Change 778 on 2003/03/03 by (Graham Barr)
Added Chinese_GB language.
Supplied by forehead (I don't even pretend tounderstand it)
Change 777 on 2003/03/03 by (Graham Barr)
Return fractional seconds when specified in an ISO date
Change 776 on 2003/03/03 by (Graham Barr)
New languages from Daniel Yacob
Change 775 on 2003/03/03 by (Graham Barr)
Fix UTC support on ISO dates
Change 774 on 2003/03/03 by (Graham Barr)
Allow a : in a timezone so the dates specified in RSS can be parsed
(eg 2002-11-07T23:31:49-05:00) Patch from Kellan
Change 773 on 2003/03/03 by (Graham Barr)
Support parsing more formats
Change 754 on 2002/11/03 by (Graham Barr)
Release 1.14
Change 753 on 2002/11/03 by (Graham Barr)
Fix bug parsing 2002-11-02 11pm
Change 752 on 2002/11/03 by (Graham Barr)
Add Greek language module from Matthew Musgrove
Change 744 on 2002/09/16 by (Graham Barr)
Add Date::Language::Brazilian and Date::Language::Danish
to MANIFEST
Change 743 on 2002/09/16 by (Graham Barr)
Add Date::Language::Brazilian from Christian Tosta
Add Date::Language::Danish from Lars Skj?lund
Change 742 on 2002/09/16 by (Graham Barr)
Time::Zone
- Add some zones for Brazil
Change 741 on 2002/09/16 by (Graham Barr)
Time::Zone [cpan #1299]
- Allow $ENV{TZ} to have zomes like EST5
Change 733 on 2002/06/13 by (Graham Barr)
Date::Language::French
- Fix missing ;
Change 732 on 2002/06/06 by (Graham Barr)
Release 1.13
Change 731 on 2002/06/06 by (Graham Barr)
Fix pattern to allow single digits for month and day (eg '2002-6-1')
Change 730 on 2002/06/03 by (Graham Barr)
Release 1.12
Change 729 on 2002/06/03 by (Graham Barr)
Fix month name abbreviations
Change 720 on 2002/04/25 by (Graham Barr)
Date::Parse
- Make it work with 5.004 again
Change 719 on 2002/04/25 by (Graham Barr)
Prevent the ISO date pattern matching where it should not. ie there must not
be a non-space character directly before the date string
Change 718 on 2002/04/17 by (Graham Barr)
Change French @Dsuf, from Peter Samuelson
Change 712 on 2002/03/07 by (Graham Barr)
Added %L format for month number as 1..12 from Adam Monsen
Change 708 on 2002/02/28 by (Graham Barr)
Release 1.11
Change 707 on 2002/02/28 by (Graham Barr)
Fix format error in t/date.t
Change 692 on 2002/01/09 by (Graham Barr)
Be a bit more lenient on the ISO format
Change 691 on 2002/01/02 by (Graham Barr)
Fix typo in ISO-8601 formats in docs
Change 690 on 2001/12/28 by (Graham Barr)
Date::Format
- Fix array dereference syntax typo
Change 689 on 2001/12/28 by (Graham Barr)
Date::Format
- Fix doc typos
Change 682 on 2001/11/20 by (Graham Barr)
Date::Parse
- Make the minutes and seconds parts of an ISO-8601 optional
(patch from Christian Hammers)
Change 681 on 2001/11/20 by (Graham Barr)
Date::Parse
- Allow AM/PM to be just A/P (eg Jul 13 1999 1:23P) as used by MySQL
(patch from Drew Degentesh)
Change 680 on 2001/11/20 by (Graham Barr)
Time::Zone
- Add CEST Central European Daylight
Change 679 on 2001/11/20 by (Graham Barr)
Date::Parse
- Extract (but ignore) fractions of a second in an ISO8601 date string
(patch from rayg at yahoo-inc.com)
Change 678 on 2001/11/20 by (Graham Barr)
Add %P to be am or pm
Change 677 on 2001/11/20 by (Graham Barr)
Date::Language::French
- Um, the french have 7 days in the week just like everyone else
Change 676 on 2001/11/20 by (Graham Barr)
Date::Language::German
- Fix abbrev for October (patch from Stefan Niederhauser)
Change 634 on 2001/09/03 by (Graham Barr)
Add a check for invalid years in format 1995-01-24
Change 580 on 2000/09/04 by (Graham Barr)
Release 1.10
Change 579 on 2000/09/04 by (Graham Barr)
Date::Parse
- Support for more date formats
Time::Zone
- Added more zones
Change 539 on 2000/06/14 by (Graham Barr)
Documentation updates
Change 536 on 2000/06/06 by (Graham Barr)
Fix VERSION numbers
Change 535 on 2000/06/06 by (Graham Barr)
Date::Format
- Added support for %O* to support output of roman numerals
Change 443 on 2000/03/29 by (Graham Barr)
Release 1.09
Change 442 on 2000/03/29 by (Graham Barr)
Added PPD stuff to Makefile.PL
Change 441 on 2000/03/29 by (Graham Barr)
Date::Parse
- Allow "s after the timezone
Change 440 on 2000/03/29 by (Graham Barr)
Date::Format
- Fix doc for %c and %C
Change 409 on 2000/03/28 by (Graham Barr)
Moved .pm files into lib directory
Change 408 on 2000/03/28 by (Graham Barr)
str2time returns undef on error bit Time::Local returns
-1. Check if the -1 is real or an error
Change 407 on 2000/03/28 by (Graham Barr)
Added Eastern European Summer Time EEST
Change 268 on 1999/03/18 by (Graham Barr)
Date::Format, Time::Zone
- Fix problem with %z and %Z as suggested by
Jason A Smith
Change 267 on 1999/03/18 by (Graham Barr)
- Make t/getdate.t more portable as suggested by
Paul Schinder
Change 250 on 1999/02/06 by (Graham Barr)
Date::Format
- Correct docs for %d and %e
Change 249 on 1999/02/06 by (Graham Barr)
Added Date::Language::Czech
Change 180 on 1998/08/05 by (Graham Barr)
Date::Language
- Added Date::Language::French contributed by
Emmanuel Bataille (bem@residents.frmug.org)
- Split out the languages into .pm's
Date::Parse
- Added patch from Alan Burlison to Date::Parse to allow zone
offests +7, +10 and +700
- Parse now supports GMT+0100
*** Release 1.08
Fri Jan 2 1998 (Graham Barr)
Date::Format, Time::Zone
- Fix for formatting %z and %Z
all
- Update Email address and year
Tue Feb 17 1998 (Graham Barr)
Date::Language
- Added format_o to German
Fri Sep 12 1997 (Graham Barr)
Date::Parse
- Added 'DST' to parser, it adjusts $zone by 3600 (but that may not
be right in all cases)
- Added a check to str2time to ensure valid
values are passed to Time::Local, to avoid croak-ing
- Fixed to treat AM and PM correctly when the hour is 12. (I hope :-)
Time::Zone
- Modified for Western Australia
Tue 07 Jan 1996
o Release 1.07
o Fixed a problem in Time::Zone (had @l[8] instead of $l[8], doh! )
Thu 02 Jan 1996
o Release 1.06
o Fixed t/getdate.t
o Date::Parse can now parse the date-format 960913, which apparently
is fairly common in sweden.
Wed 31 Jul 1996
o Release 1.05
o Modified Date::Format not to use single letter sub names,
all format sub names are nore prefixed with format_
o Cleaned up Date/Format.pm so that AUTOLOAD is not required
o Patched Date/Language.pm to add Norwegian. Thanks to
Gisle Aas for the patch
Thu 27 Jun 1996
o Added %z to Date::Format to output timezone in +/-0000 format
o Added multi-language support via Date::Language,.
Tue 25 Jun 1996
o Some code tidying up
o added a new test, copied from Date::GetDate
o improved performance
Wed 22 May 1996
o Fixed a bug in the parser for dates in a default (local) timezone
but a different dst
Wed 15 May 1996
o Added support for mainframe type dates
Fri 3 May 1996
o Added %s to date formatting at request of Josh Osborne
.
META.yml 100644 000765 000024 40324 15157412057 14437 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 ---
abstract: 'Date and time formatting subroutines'
author:
- 'Graham '
build_requires:
ExtUtils::MakeMaker: '0'
File::Spec: '0'
Test::More: '0'
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 0
generated_by: 'Dist::Zilla version 6.033, CPAN::Meta::Converter version 2.150010'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: TimeDate
provides:
Date::Format:
file: lib/Date/Format.pm
version: '2.35'
Date::Format::Generic:
file: lib/Date/Format/Generic.pm
version: '2.35'
Date::Language:
file: lib/Date/Language.pm
version: '2.35'
Date::Language::Afar:
file: lib/Date/Language/Afar.pm
version: '2.35'
Date::Language::Amharic:
file: lib/Date/Language/Amharic.pm
version: '2.35'
Date::Language::Arabic:
file: lib/Date/Language/Arabic.pm
version: '2.35'
Date::Language::Austrian:
file: lib/Date/Language/Austrian.pm
version: '2.35'
Date::Language::Brazilian:
file: lib/Date/Language/Brazilian.pm
version: '2.35'
Date::Language::Bulgarian:
file: lib/Date/Language/Bulgarian.pm
version: '2.35'
Date::Language::Chinese:
file: lib/Date/Language/Chinese.pm
version: '2.35'
Date::Language::Chinese_GB:
file: lib/Date/Language/Chinese_GB.pm
version: '2.35'
Date::Language::Czech:
file: lib/Date/Language/Czech.pm
version: '2.35'
Date::Language::Danish:
file: lib/Date/Language/Danish.pm
version: '2.35'
Date::Language::Dutch:
file: lib/Date/Language/Dutch.pm
version: '2.35'
Date::Language::English:
file: lib/Date/Language/English.pm
version: '2.35'
Date::Language::Finnish:
file: lib/Date/Language/Finnish.pm
version: '2.35'
Date::Language::French:
file: lib/Date/Language/French.pm
version: '2.35'
Date::Language::Gedeo:
file: lib/Date/Language/Gedeo.pm
version: '2.35'
Date::Language::German:
file: lib/Date/Language/German.pm
version: '2.35'
Date::Language::Greek:
file: lib/Date/Language/Greek.pm
version: '2.35'
Date::Language::Hungarian:
file: lib/Date/Language/Hungarian.pm
version: '2.35'
Date::Language::Icelandic:
file: lib/Date/Language/Icelandic.pm
version: '2.35'
Date::Language::Italian:
file: lib/Date/Language/Italian.pm
version: '2.35'
Date::Language::Norwegian:
file: lib/Date/Language/Norwegian.pm
version: '2.35'
Date::Language::Occitan:
file: lib/Date/Language/Occitan.pm
version: '2.35'
Date::Language::Oromo:
file: lib/Date/Language/Oromo.pm
version: '2.35'
Date::Language::Portuguese:
file: lib/Date/Language/Portuguese.pm
version: '2.35'
Date::Language::Romanian:
file: lib/Date/Language/Romanian.pm
version: '2.35'
Date::Language::Russian:
file: lib/Date/Language/Russian.pm
version: '2.35'
Date::Language::Russian_cp1251:
file: lib/Date/Language/Russian_cp1251.pm
version: '2.35'
Date::Language::Russian_koi8r:
file: lib/Date/Language/Russian_koi8r.pm
version: '2.35'
Date::Language::Sidama:
file: lib/Date/Language/Sidama.pm
version: '2.35'
Date::Language::Somali:
file: lib/Date/Language/Somali.pm
version: '2.35'
Date::Language::Spanish:
file: lib/Date/Language/Spanish.pm
version: '2.35'
Date::Language::Swedish:
file: lib/Date/Language/Swedish.pm
version: '2.35'
Date::Language::Tigrinya:
file: lib/Date/Language/Tigrinya.pm
version: '2.35'
Date::Language::TigrinyaEritrean:
file: lib/Date/Language/TigrinyaEritrean.pm
version: '2.35'
Date::Language::TigrinyaEthiopian:
file: lib/Date/Language/TigrinyaEthiopian.pm
version: '2.35'
Date::Language::Turkish:
file: lib/Date/Language/Turkish.pm
version: '2.35'
Date::Parse:
file: lib/Date/Parse.pm
version: '2.35'
Time::Zone:
file: lib/Time/Zone.pm
version: '2.35'
TimeDate:
file: lib/TimeDate.pm
version: '2.35'
requires:
Carp: '0'
resources:
bugtracker: https://github.com/cpan-authors/TimeDate/issues
repository: https://github.com/cpan-authors/TimeDate.git
version: '2.35'
x_Dist_Zilla:
perl:
version: '5.038004'
plugins:
-
class: Dist::Zilla::Plugin::OurPkgVersion
name: OurPkgVersion
version: '0.21'
-
class: Dist::Zilla::Plugin::Test::Compile
config:
Dist::Zilla::Plugin::Test::Compile:
bail_out_on_fail: 0
fail_on_warning: author
fake_home: 0
filename: xt/author/00-compile.t
module_finder:
- ':InstallModules'
needs_display: 0
phase: develop
script_finder:
- ':PerlExecFiles'
skips: []
switch: []
name: Test::Compile
version: '2.058'
-
class: Dist::Zilla::Plugin::MetaTests
name: MetaTests
version: '6.033'
-
class: Dist::Zilla::Plugin::Test::NoTabs
config:
Dist::Zilla::Plugin::Test::NoTabs:
filename: xt/author/no-tabs.t
finder:
- ':InstallModules'
- ':ExecFiles'
- ':TestFiles'
name: Test::NoTabs
version: '0.15'
-
class: Dist::Zilla::Plugin::PodSyntaxTests
name: PodSyntaxTests
version: '6.033'
-
class: Dist::Zilla::Plugin::Test::ReportPrereqs
name: Test::ReportPrereqs
version: '0.029'
-
class: Dist::Zilla::Plugin::PodWeaver
config:
Dist::Zilla::Plugin::PodWeaver:
finder:
- ':InstallModules'
- ':PerlExecFiles'
plugins:
-
class: Pod::Weaver::Plugin::EnsurePod5
name: '@CorePrep/EnsurePod5'
version: '4.020'
-
class: Pod::Weaver::Plugin::H1Nester
name: '@CorePrep/H1Nester'
version: '4.020'
-
class: Pod::Weaver::Plugin::SingleEncoding
name: '@Default/SingleEncoding'
version: '4.020'
-
class: Pod::Weaver::Section::Name
name: '@Default/Name'
version: '4.020'
-
class: Pod::Weaver::Section::Version
name: '@Default/Version'
version: '4.020'
-
class: Pod::Weaver::Section::Region
name: '@Default/prelude'
version: '4.020'
-
class: Pod::Weaver::Section::Generic
name: SYNOPSIS
version: '4.020'
-
class: Pod::Weaver::Section::Generic
name: DESCRIPTION
version: '4.020'
-
class: Pod::Weaver::Section::Generic
name: OVERVIEW
version: '4.020'
-
class: Pod::Weaver::Section::Collect
name: ATTRIBUTES
version: '4.020'
-
class: Pod::Weaver::Section::Collect
name: METHODS
version: '4.020'
-
class: Pod::Weaver::Section::Collect
name: FUNCTIONS
version: '4.020'
-
class: Pod::Weaver::Section::Leftovers
name: '@Default/Leftovers'
version: '4.020'
-
class: Pod::Weaver::Section::Region
name: '@Default/postlude'
version: '4.020'
-
class: Pod::Weaver::Section::Authors
name: '@Default/Authors'
version: '4.020'
-
class: Pod::Weaver::Section::Legal
name: '@Default/Legal'
version: '4.020'
name: PodWeaver
version: '4.010'
-
class: Dist::Zilla::Plugin::RunExtraTests
config:
Dist::Zilla::Role::TestRunner:
default_jobs: 1
name: RunExtraTests
version: '0.029'
-
class: Dist::Zilla::Plugin::MetaJSON
name: MetaJSON
version: '6.033'
-
class: Dist::Zilla::Plugin::MetaConfig
name: MetaConfig
version: '6.033'
-
class: Dist::Zilla::Plugin::MetaProvides::Package
config:
Dist::Zilla::Plugin::MetaProvides::Package:
finder_objects:
-
class: Dist::Zilla::Plugin::FinderCode
name: MetaProvides::Package/AUTOVIV/:InstallModulesPM
version: '6.033'
include_underscores: 0
Dist::Zilla::Role::MetaProvider::Provider:
$Dist::Zilla::Role::MetaProvider::Provider::VERSION: '2.002004'
inherit_missing: 1
inherit_version: 1
meta_noindex: 1
Dist::Zilla::Role::ModuleMetadata:
Module::Metadata: '1.000037'
version: '0.006'
name: MetaProvides::Package
version: '2.004003'
-
class: Dist::Zilla::Plugin::NextRelease
name: NextRelease
version: '6.033'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: runtime
type: requires
name: RuntimeRequires
version: '6.033'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: test
type: requires
name: TestRequires
version: '6.033'
-
class: Dist::Zilla::Plugin::TestRelease
name: TestRelease
version: '6.033'
-
class: Dist::Zilla::Plugin::Test::MinimumVersion
config:
Dist::Zilla::Plugin::Test::MinimumVersion:
max_target_perl: '5.010'
name: Test::MinimumVersion
version: '2.000011'
-
class: Dist::Zilla::Plugin::Git::Check
config:
Dist::Zilla::Plugin::Git::Check:
untracked_files: die
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
- README.md
- dist.ini
allow_dirty_match: []
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: '2.50.1 (Apple Git-155)'
repo_root: .
name: '@Git/Check'
version: '2.051'
-
class: Dist::Zilla::Plugin::Git::Commit
config:
Dist::Zilla::Plugin::Git::Commit:
add_files_in:
- Changes
- README.md
- dist.ini
commit_msg: v%V%n%n%c
signoff: 0
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
- README.md
- dist.ini
allow_dirty_match: []
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: '2.50.1 (Apple Git-155)'
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Git/Commit'
version: '2.051'
-
class: Dist::Zilla::Plugin::Git::Tag
config:
Dist::Zilla::Plugin::Git::Tag:
branch: ~
changelog: Changes
signed: 0
tag: v2.35
tag_format: v%V
tag_message: v%V
Dist::Zilla::Role::Git::Repo:
git_version: '2.50.1 (Apple Git-155)'
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: '@Git/Tag'
version: '2.051'
-
class: Dist::Zilla::Plugin::Git::Push
config:
Dist::Zilla::Plugin::Git::Push:
push_to:
- origin
- 'origin HEAD:refs/heads/released'
remotes_must_exist: 1
Dist::Zilla::Role::Git::Repo:
git_version: '2.50.1 (Apple Git-155)'
repo_root: .
name: '@Git/Push'
version: '2.051'
-
class: Dist::Zilla::Plugin::Run::BeforeBuild
config:
Dist::Zilla::Plugin::Run::Role::Runner:
fatal_errors: 1
quiet: 0
version: '0.050'
name: Run::BeforeBuild
version: '0.050'
-
class: Dist::Zilla::Plugin::Run::AfterBuild
config:
Dist::Zilla::Plugin::Run::Role::Runner:
fatal_errors: 1
quiet: 0
run:
- 'cp %d/Makefile.PL ./'
- "git status --porcelain | grep 'M Makefile.PL' && git commit -m 'Makefile.PL auto-updated by dist.ini' Makefile.PL && echo \"# Makefile.PL auto-update\" || echo \"# Makefile.PL up to date\""
version: '0.050'
name: Run::AfterBuild
version: '0.050'
-
class: Dist::Zilla::Plugin::Git::NextVersion
config:
Dist::Zilla::Plugin::Git::NextVersion:
first_version: '0.001'
version_by_branch: 0
version_regexp: (?^:^v(.+)$)
Dist::Zilla::Role::Git::Repo:
git_version: '2.50.1 (Apple Git-155)'
repo_root: .
name: Git::NextVersion
version: '2.051'
-
class: Dist::Zilla::Plugin::PruneCruft
name: '@Filter/PruneCruft'
version: '6.033'
-
class: Dist::Zilla::Plugin::ManifestSkip
name: '@Filter/ManifestSkip'
version: '6.033'
-
class: Dist::Zilla::Plugin::MetaYAML
name: '@Filter/MetaYAML'
version: '6.033'
-
class: Dist::Zilla::Plugin::License
name: '@Filter/License'
version: '6.033'
-
class: Dist::Zilla::Plugin::Readme
name: '@Filter/Readme'
version: '6.033'
-
class: Dist::Zilla::Plugin::ExecDir
name: '@Filter/ExecDir'
version: '6.033'
-
class: Dist::Zilla::Plugin::ShareDir
name: '@Filter/ShareDir'
version: '6.033'
-
class: Dist::Zilla::Plugin::MakeMaker
config:
Dist::Zilla::Role::TestRunner:
default_jobs: 1
name: '@Filter/MakeMaker'
version: '6.033'
-
class: Dist::Zilla::Plugin::Manifest
name: '@Filter/Manifest'
version: '6.033'
-
class: Dist::Zilla::Plugin::TestRelease
name: '@Filter/TestRelease'
version: '6.033'
-
class: Dist::Zilla::Plugin::ConfirmRelease
name: '@Filter/ConfirmRelease'
version: '6.033'
-
class: Dist::Zilla::Plugin::UploadToCPAN
name: '@Filter/UploadToCPAN'
version: '6.033'
-
class: Dist::Zilla::Plugin::GatherDir
config:
Dist::Zilla::Plugin::GatherDir:
exclude_filename:
- CLAUDE.md
- Makefile.PL
exclude_match: []
follow_symlinks: 0
include_dotfiles: 0
prefix: ''
prune_directory: []
root: .
name: GatherDir
version: '6.033'
-
class: Dist::Zilla::Plugin::MetaResources
name: MetaResources
version: '6.033'
-
class: Dist::Zilla::Plugin::PruneFiles
name: PruneFiles
version: '6.033'
-
class: Dist::Zilla::Plugin::InsertExample
name: InsertExample
version: '0.15'
-
class: Dist::Zilla::Plugin::Test::Synopsis
name: Test::Synopsis
version: '2.000007'
-
class: Dist::Zilla::Plugin::ReadmeAnyFromPod
config:
Dist::Zilla::Role::FileWatcher:
version: '0.006'
name: ReadmeAnyFromPod
version: '0.163250'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':InstallModules'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':IncModules'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':TestFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExtraTestFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExecFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':PerlExecFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ShareFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':MainModule'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':AllFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':NoFiles'
version: '6.033'
-
class: Dist::Zilla::Plugin::FinderCode
name: MetaProvides::Package/AUTOVIV/:InstallModulesPM
version: '6.033'
zilla:
class: Dist::Zilla::Dist::Builder
config:
is_trial: 0
version: '6.033'
x_generated_by_perl: v5.38.4
x_serialization_backend: 'YAML::Tiny version 1.76'
x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later'
MANIFEST 100644 000765 000024 3601 15157412057 14274 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.033.
Changes
LICENSE
MANIFEST
META.json
META.yml
Makefile.PL
README
SECURITY.md
dist.ini
lib/Date/Format.pm
lib/Date/Format/Generic.pm
lib/Date/Language.pm
lib/Date/Language/Afar.pm
lib/Date/Language/Amharic.pm
lib/Date/Language/Arabic.pm
lib/Date/Language/Austrian.pm
lib/Date/Language/Brazilian.pm
lib/Date/Language/Bulgarian.pm
lib/Date/Language/Chinese.pm
lib/Date/Language/Chinese_GB.pm
lib/Date/Language/Czech.pm
lib/Date/Language/Danish.pm
lib/Date/Language/Dutch.pm
lib/Date/Language/English.pm
lib/Date/Language/Finnish.pm
lib/Date/Language/French.pm
lib/Date/Language/Gedeo.pm
lib/Date/Language/German.pm
lib/Date/Language/Greek.pm
lib/Date/Language/Hungarian.pm
lib/Date/Language/Icelandic.pm
lib/Date/Language/Italian.pm
lib/Date/Language/Norwegian.pm
lib/Date/Language/Occitan.pm
lib/Date/Language/Oromo.pm
lib/Date/Language/Portuguese.pm
lib/Date/Language/Romanian.pm
lib/Date/Language/Russian.pm
lib/Date/Language/Russian_cp1251.pm
lib/Date/Language/Russian_koi8r.pm
lib/Date/Language/Sidama.pm
lib/Date/Language/Somali.pm
lib/Date/Language/Spanish.pm
lib/Date/Language/Swedish.pm
lib/Date/Language/Tigrinya.pm
lib/Date/Language/TigrinyaEritrean.pm
lib/Date/Language/TigrinyaEthiopian.pm
lib/Date/Language/Turkish.pm
lib/Date/Parse.pm
lib/Time/Zone.pm
lib/TimeDate.pm
t/00-report-prereqs.dd
t/00-report-prereqs.t
t/cpanrt-format.t
t/cpanrt-language.t
t/cpanrt-overflow.t
t/cpanrt-parse.t
t/cpanrt-zone.t
t/date.t
t/edge-cases.t
t/format.t
t/getdate.t
t/gh10.t
t/gh12.t
t/lang-data.t
t/lang-encoding.t
t/lang.t
t/msk-tz.t
t/pod-valid.t
t/rt-format.t
t/rt-parse.t
t/rt-timezone.t
t/rt106105.t
t/rt52387.t
t/rt57800.t
t/str2time-epoch.t
t/strptime-iso8601.t
t/time2str-lang.t
t/tz-lang.t
t/zone.t
xt/author/00-compile.t
xt/author/distmeta.t
xt/author/minimum-version.t
xt/author/no-tabs.t
xt/author/pod-syntax.t
xt/author/synopsis.t
dist.ini 100644 000765 000024 4411 15157412057 14607 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 name = TimeDate
author = Graham
license = Perl_5
copyright_holder = Graham Barr
copyright_year = 2020
;[PPPort]
;[PkgVersion]
[OurPkgVersion]
[Test::Compile]
xt_mode = 1
[MetaTests]
[Test::NoTabs]
[PodSyntaxTests]
[Test::ReportPrereqs]
[PodWeaver]
[RunExtraTests]
[MetaJSON]
;[MinimumPerlFast]
;min = 5.010 ; undocumented config!
;max = 5.010 ; undocumented config!
[MetaConfig]
[MetaProvides::Package]
[NextRelease]
filename = Changes
;[Prereqs::FromCPANfile]
;[Prereqs / RuntimeRecommends]
[Prereqs / RuntimeRequires]
Carp = 0
;[Prereqs / TestRecommends]
[Prereqs / TestRequires]
;Test2::Bundle::Extended = 0
;Test2::Tools::Explain = 0
;Test2::Plugin::NoWarnings = 0
;Devel::Peek = 0
[TestRelease]
[Test::MinimumVersion]
max_target_perl = 5.010
[@Git]
allow_dirty = Changes
allow_dirty = dist.ini
allow_dirty = README.md
add_files_in = Changes
add_files_in = dist.ini
add_files_in = README.md
push_to = origin
push_to = origin HEAD:refs/heads/released ; also push to released branch
[Run::BeforeBuild]
; force to refresh Makefile.PL for every build [not really necessary as we have one exclude_filename]
; run = ( test -f Makefile.PL && rm Makefile.PL ) ||:
[Run::AfterBuild]
; provide a friendly Makefile.PL in our repo
; very useful so Travis CI can use it without installing Dist::Zilla::*
run = cp %d/Makefile.PL ./
run = git status --porcelain | grep 'M Makefile.PL' && git commit -m 'Makefile.PL auto-updated by dist.ini' Makefile.PL && echo "# Makefile.PL auto-update" || echo "# Makefile.PL up to date"
[Git::NextVersion]
[@Filter]
-bundle = @Basic
;-remove = AutoPrereqs
-remove = ExtraTests
-remove = GatherDir
[GatherDir]
exclude_filename = Makefile.PL
exclude_filename = CLAUDE.md
;exclude_filename = ppport.h
; -- static meta-information
[MetaResources]
bugtracker.web = https://github.com/cpan-authors/TimeDate/issues
repository.url = https://github.com/cpan-authors/TimeDate.git
repository.web = https://github.com/cpan-authors/TimeDate
repository.type = git
[PruneFiles]
match = ~$ ; emacs backup files
;[PodCoverageTests]
;[Test::EOL]
; still a work in progress
;[Test::TidyAll]
;minimum_perl = 5.010
;jobs = 1
;verbose = 1
[InsertExample]
[Test::Synopsis]
[ReadmeAnyFromPod]
type = gfm
filename = README.md
location = root
t 000755 000765 000024 0 15157412057 13246 5 ustar 00nicolas staff 000000 000000 TimeDate-2.35 zone.t 100644 000765 000024 7403 15157412057 14552 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Time::Zone;
# tz_offset: standard timezone abbreviations
is(tz_offset("GMT"), 0, "tz_offset GMT = 0");
is(tz_offset("UTC"), 0, "tz_offset UTC = 0");
is(tz_offset("EST"), -18000, "tz_offset EST = -18000");
is(tz_offset("CST"), -21600, "tz_offset CST = -21600");
is(tz_offset("MST"), -25200, "tz_offset MST = -25200");
is(tz_offset("PST"), -28800, "tz_offset PST = -28800");
is(tz_offset("CET"), 3600, "tz_offset CET = 3600");
is(tz_offset("JST"), 32400, "tz_offset JST = 32400");
is(tz_offset("IST"), 19800, "tz_offset IST = 19800");
is(tz_offset("NST"), -12600, "tz_offset NST = -12600 (Newfoundland Standard)");
is(tz_offset("NFT"), -12600, "tz_offset NFT = -12600 (Newfoundland)");
# tz_offset: Newfoundland Daylight (half-hour DST)
is(tz_offset("NDT"), -9000, "tz_offset NDT = -9000 (Newfoundland Daylight)");
# tz_offset: DST timezone abbreviations
is(tz_offset("EDT"), -14400, "tz_offset EDT = -14400");
is(tz_offset("CDT"), -18000, "tz_offset CDT = -18000");
is(tz_offset("MDT"), -21600, "tz_offset MDT = -21600");
is(tz_offset("PDT"), -25200, "tz_offset PDT = -25200");
is(tz_offset("BST"), 3600, "tz_offset BST = 3600");
is(tz_offset("CEST"), 7200, "tz_offset CEST = 7200");
# tz_offset: numeric offsets
is(tz_offset("+0000"), 0, "tz_offset +0000 = 0");
is(tz_offset("-0500"), -18000, "tz_offset -0500 = -18000");
is(tz_offset("+0530"), 19800, "tz_offset +0530 = 19800");
is(tz_offset("+0900"), 32400, "tz_offset +0900 = 32400");
is(tz_offset("-0800"), -28800, "tz_offset -0800 = -28800");
# tz_offset: Southeast Asian timezones (RT#123247)
is(tz_offset("ICT"), 25200, "tz_offset ICT = 25200 (Indochina Time, UTC+7)");
is(tz_offset("PHT"), 28800, "tz_offset PHT = 28800 (Philippine Time, UTC+8)");
is(tz_offset("ict"), 25200, "tz_offset ict case insensitive");
is(tz_offset("pht"), 28800, "tz_offset pht case insensitive");
# tz_offset: unknown zone returns undef
is(tz_offset("BOGUS"), undef, "tz_offset unknown zone returns undef");
# tz_offset: case insensitivity
is(tz_offset("gmt"), 0, "tz_offset case insensitive: gmt");
is(tz_offset("est"), -18000, "tz_offset case insensitive: est");
# tz_name: with explicit $dst parameter (deterministic, no system-time dependency)
# When $dst=0, offset -18000 (-5h) should resolve to a standard timezone (EST)
# When $dst=1, offset -18000 (-5h) should resolve to a DST timezone (CDT)
is(tz_name(-18000, 0), "est", "tz_name(-18000, dst=0) is est");
is(tz_name(-18000, 1), "cdt", "tz_name(-18000, dst=1) is cdt");
# tz_name: offset 0 is always GMT/UTC regardless of DST flag
like(tz_name(0, 0), qr/^(?:gmt|utc)$/i, "tz_name(0, dst=0) is GMT or UTC");
like(tz_name(0, 1), qr/^(?:gmt|utc)$/i, "tz_name(0, dst=1) is GMT or UTC");
# tz_name: offsets with only standard or only DST entries
is(tz_name(32400, 0), "jst", "tz_name(32400, dst=0) is jst (Japan Standard)");
is(tz_name(-25200, 1), "pdt", "tz_name(-25200, dst=1) is pdt (Pacific Daylight)");
is(tz_name(-28800, 0), "pst", "tz_name(-28800, dst=0) is pst (Pacific Standard)");
# tz_name: unknown offset returns correct +HHMM numeric string (RT#59298)
# 5400s = 90 minutes = UTC+1:30 → "+0130" (not "+9000" which the buggy code produced)
is(tz_name(5400, 0), "+0130", "tz_name(5400) returns +0130 (UTC+1:30)");
# Negative fractional-hour offset: -5400s = UTC-1:30 → "-0130"
# (Note: -9000 is now NDT/Newfoundland Daylight, so use -5400 instead)
is(tz_name(-5400, 0), "-0130", "tz_name(-5400) returns -0130 (UTC-1:30)");
# tz_local_offset: returns a sane value
{
my $offset = tz_local_offset();
ok(defined $offset, "tz_local_offset returns defined value");
cmp_ok($offset, '>=', -12 * 3600, "tz_local_offset >= -12 hours");
cmp_ok($offset, '<=', 14 * 3600, "tz_local_offset <= 14 hours");
}
done_testing;
gh12.t 100644 000765 000024 2204 15157412057 14332 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 3;
use Date::Parse qw(strptime str2time);
# GH#12 / RT#84075: Date::Parse::str2time maps date in 1963 to 2063
# Root cause: str2time passed a 2-digit year to timegm, triggering its 50-year
# sliding window. The fix: strptime extracts the century and returns year as
# offset-from-1900; str2time reconstructs the full 4-digit year before calling
# timegm, bypassing the windowing entirely.
{
my $this_year = 1900 + (gmtime(time))[5];
my $target_year = $this_year - 50;
my $date = "$target_year-01-01 00:00:00 UTC";
my $time = str2time($date);
my $year_parsed_as = 1900 + (gmtime($time))[5];
is($year_parsed_as, $target_year, "GH#12: year $target_year not mapped to future");
# Canonical example from the original bug report (year 1963)
my $t1963 = str2time("1963-12-31 23:59:59 UTC");
my $got1963 = 1900 + (gmtime($t1963))[5];
is($got1963, 1963, "GH#12: 1963-12-31 not mapped to 2063");
# strptime must capture the century for 4-digit years
my @t = strptime("1963-12-31 23:59:59 UTC");
is($t[7], 19, "GH#12: strptime century field is 19 for 1963");
}
date.t 100644 000765 000024 11777 15157412057 14545 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Parse;
use Date::Format qw(time2str);
my @data = split /\n/, <<'DATA';
1995-01-24
1995-01-24T09:08:17.1823213
- 1935-01-24T09:08:17
- Fri Dec 17 00:00:00 1901 GMT
Tue Jan 16 23:59:59 2038 GMT
2001-02-02 00:00:00 GMT
2035-02-02 00:00:00 GMT
- 16 Jun 33 07:29:35 CST
2002-02-26-10:37:21.141 GMT
Wed, 16 Jun 94 07:29:35 CST
Wed, 16 Nov 94 07:29:35 CST
Mon, 21 Nov 94 07:42:23 CST
Mon, 21 Nov 94 04:28:18 CST
Tue, 15 Nov 94 09:15:10 GMT
Wed, 16 Nov 94 09:39:49 GMT
Wed, 16 Nov 94 09:23:17 GMT
Wed, 16 Nov 94 12:39:49 GMT
Wed, 16 Nov 94 14:03:06 GMT
Wed, 16 Nov 94 05:30:51 CST
Thu, 17 Nov 94 03:19:30 CST
Mon, 21 Nov 94 14:05:32 GMT
Mon, 14 Nov 94 15:08:49 CST
Wed, 16 Nov 94 14:48:06 GMT
Thu, 17 Nov 94 14:22:03 GMT
Wed, 16 Nov 94 14:36:00 GMT
Wed, 16 Nov 94 09:23:17 GMT
Wed, 16 Nov 94 10:01:43 GMT
Wed, 16 Nov 94 15:03:35 GMT
Mon, 21 Nov 94 13:55:19 GMT
Wed, 16 Nov 94 08:46:11 CST
21 dec 17:05
21-dec 17:05
21/dec 17:05
21/dec/93 17:05
dec/21/93 17:05
Dec/21/1993 17:05:00
dec-21-1993 17:05
Dec-21-93 17:05:00
dec 21 1994 17:05
dec 21 94 17:05
dec 21 94 17:05 GMT
dec 21 94 17:05 BST
dec 21 94 00:05 -1700
dec 21 94 17:05 -1700
Wed, 9 Nov 1994 09:50:32 -0500 (EST)
Thu, 13 Oct 94 10:13:13 -0700
Sat, 19 Nov 1994 16:59:14 +0100
Thu, 3 Nov 94 14:10:47 EST
Thu, 3 Nov 94 21:51:09 EST
Fri, 4 Nov 94 9:24:52 EST
Wed, 9 Nov 94 09:38:54 EST
Mon, 14 Nov 94 13:20:12 EST
Wed, 16 Nov 94 17:09:13 EST
Tue, 15 Nov 94 12:27:01 PST
Fri, 18 Nov 1994 07:34:05 -0600
Mon, 21 Nov 94 14:34:28 -0500
Fri, 18 Nov 1994 12:05:47 -0800 (PST)
Fri, 18 Nov 1994 12:36:26 -0800 (PST)
Wed, 16 Nov 1994 15:58:58 GMT
2000 10:02:18 "GMT"
Sun, 06 Nov 94 14:27:40 -0500
Mon, 07 Nov 94 08:20:13 -0500
Mon, 07 Nov 94 16:48:42 -0500
Wed, 09 Nov 94 15:46:16 -0500
Fri, 4 Nov 94 16:17:40 "PST
Wed, 16 Nov 94 12:43:37 "PST
Sun, 6 Nov 1994 02:38:17 -0800
Tue, 1 Nov 1994 13:53:49 -0500
Tue, 15 Nov 94 08:31:59 +0100
Sun, 6 Nov 1994 11:09:12 -0500 (IST)
Fri, 4 Nov 94 12:52:10 EST
Mon, 31 Oct 1994 14:17:39 -0500 (EST)
Mon, 14 Nov 94 11:25:00 CST
Mon, 14 Nov 94 13:26:29 CST
Fri, 18 Nov 94 8:42:47 CST
Thu, 17 Nov 94 14:32:01 +0900
Wed, 2 Nov 94 18:16:31 +0100
Fri, 18 Nov 94 10:46:26 +0100
Tue, 8 Nov 1994 22:39:28 +0200
Wed, 16 Nov 1994 10:01:08 -0500 (EST)
Wed, 2 Nov 1994 16:59:42 -0800
Wed, 9 Nov 94 10:00:23 PST
Fri, 18 Nov 94 17:01:43 PST
Mon, 14 Nov 1994 14:47:46 -0500
Mon, 21 Nov 1994 04:56:04 -0500 (EST)
Mon, 21 Nov 1994 11:50:12 -0800
Sat, 5 Nov 1994 14:04:16 -0600 (CST)
Sat, 05 Nov 94 13:10:13 MST
Wed, 02 Nov 94 10:47:48 -0800
Wed, 02 Nov 94 13:19:15 -0800
Thu, 03 Nov 94 15:27:07 -0800
Fri, 04 Nov 94 09:12:12 -0800
Wed, 9 Nov 1994 10:13:03 +0000 (GMT)
Wed, 9 Nov 1994 15:28:37 +0000 (GMT)
Wed, 2 Nov 1994 17:37:41 +0100 (MET)
05 Nov 94 14:22:19 PST
16 Nov 94 22:28:20 PST
Tue, 1 Nov 1994 19:51:15 -0800
Wed, 2 Nov 94 12:21:23 GMT
Fri, 18 Nov 94 18:07:03 GMT
Wed, 16 Nov 1994 11:26:27 -0500
Sun, 6 Nov 1994 13:48:49 -0500
Tue, 8 Nov 1994 13:19:37 -0800
Fri, 18 Nov 1994 11:01:12 -0800
Mon, 21 Nov 1994 00:47:58 -0500
Mon, 7 Nov 1994 14:22:48 -0800 (PST)
Wed, 16 Nov 1994 15:56:45 -0800 (PST)
Thu, 3 Nov 1994 13:17:47 +0000
Wed, 9 Nov 1994 17:32:50 -0500 (EST)
Wed, 9 Nov 94 16:31:52 PST
Wed, 09 Nov 94 10:41:10 -0800
Wed, 9 Nov 94 08:42:22 MST
Mon, 14 Nov 1994 08:32:13 -0800
Mon, 14 Nov 1994 11:34:32 -0500 (EST)
Mon, 14 Nov 94 16:48:09 GMT
Tue, 15 Nov 1994 10:27:33 +0000
Wed, 02 Nov 94 13:56:54 MST
Thu, 03 Nov 94 15:24:45 MST
Thu, 3 Nov 1994 15:13:53 -0700 (MST)
Fri, 04 Nov 94 08:15:13 MST
Thu, 3 Nov 94 18:15:47 EST
Tue, 08 Nov 94 07:02:33 MST
Thu, 3 Nov 94 18:15:47 EST
Tue, 15 Nov 94 07:26:05 MST
Wed, 2 Nov 1994 00:00:55 -0600 (CST)
Sun, 6 Nov 1994 01:19:13 -0600 (CST)
Mon, 7 Nov 1994 23:16:57 -0600 (CST)
Tue, 08 Nov 1994 13:21:21 -0600
Mon, 07 Nov 94 13:47:37 PST
Tue, 08 Nov 94 11:23:19 PST
Tue, 01 Nov 1994 11:28:25 -0800
Tue, 15 Nov 1994 13:11:47 -0800
Tue, 15 Nov 1994 13:18:38 -0800
Tue, 15 Nov 1994 0:18:38 -0800
10:00:00Z
10:00:00
10:00
10:00 +100
10:00 +0100
20020722T100000Z
Jul 22 10:00:00 UTC 2002
2002-07-22 10:00:00Z
2002-07-22 10:00:00 Z
2002-07-22 10:00 Z
2002-07-22 10:00Z
2002-07-22 10:00 +100
2002-07-22 10:00 +0100
2002-Jul-22 10:00:00.000000
2002-July-22 10:00:00.000000
DATA
ok(!defined(str2time("")), "empty string returns undef");
# NOTE: the "2000 10:02:18 GMT" entry above uses a leap year (2000) deliberately.
# When only a year is given, str2time fills in the current month/day. On Feb 29
# the year must be a leap year or the date is invalid and the test fails.
# See: https://github.com/atoomic/perl-TimeDate/issues/28
for my $date (@data) {
my $pre_1970 = ($date =~ s/^-\s*//);
SKIP: {
skip "pre-1970 dates on Win32", 1 if $pre_1970 && $^O eq "MSWin32";
my $time = str2time($date);
if (defined $time) {
$time = int $time;
my $formatted = time2str("%a %b %e %T %Y %Z", $time, 'GMT');
my $reparsed = str2time($formatted);
is($reparsed, $time, "round-trip: $date");
}
else {
fail("parse failed: $date");
}
}
}
done_testing;
lang.t 100644 000765 000024 737 15157412057 14503 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Language;
my $time = time;
my @lang = qw(
English German Italian Bulgarian
French Spanish Swedish Norwegian
Danish Dutch Romanian Czech
Hungarian Finnish Austrian Brazilian
Portuguese Turkish
);
for my $lang (@lang) {
my $l = Date::Language->new($lang);
my $str = $l->ctime($time);
my $parsed = $l->str2time($str);
is($parsed, $time, "$lang: round-trip ctime/str2time");
}
done_testing;
gh10.t 100644 000765 000024 4541 15157412057 14336 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
# GH#10 / RT#80649: Wrong timezone abbreviation during DST fall-back
#
# format_Z was calling timelocal() to reconstruct the original epoch from
# broken-down time. During the "fall-back" hour, the broken-down time is
# ambiguous (1:xx AM occurs twice: once in PDT and once in PST). timelocal()
# resolves the ambiguity to the first occurrence (PDT), returning the PDT
# epoch (offset -25200). tz_name(-25200, dst=0) then finds -25200 in %zoneOff
# as "mst" (Mountain Standard), yielding MST instead of PST.
#
# Fix: use the original epoch stored in $_[0]->[9] instead of timelocal().
#
# The TZ is set in a BEGIN block so the C library timezone is initialised
# before any module loads and before any localtime/tzset calls happen.
# Using a runtime $ENV{TZ} assignment after `use` statements is unreliable
# because `use` executes at compile time, and on some platforms restoring a
# `local $ENV{TZ}` automatically resets the C library timezone, which a later
# POSIX::tzset() call may not fully undo.
BEGIN {
$ENV{TZ} = 'America/Los_Angeles';
require POSIX;
eval { POSIX::tzset() };
}
use POSIX qw();
use Test::More;
use Date::Format qw(time2str);
# Skip the whole file if the platform does not support IANA timezone names.
# Use epoch 1352019262 (2012-11-04 01:04:22 PDT): DST=1 in America/Los_Angeles
# but DST=0 in UTC, so this check actually distinguishes the two and won't
# produce a false-positive on a UTC-only system.
my $has_la_tz = eval {
my @lt = localtime(1352019262); # 2012-11-04 01:04:22 PDT (before fall-back)
$lt[8] == 1; # Expect DST flag = 1 in PDT
};
plan( skip_all => "system does not support America/Los_Angeles timezone" )
unless $has_la_tz;
plan tests => 3;
# 2012-11-04 01:25:05 PST — the second occurrence of 01:xx AM after fall-back
# This is the timestamp from the original bug report that returned MST.
is( time2str("%Z", 1352021105), "PST",
"GH#10/RT#80649: repeated hour after fall-back formats as PST, not MST" );
# 2012-11-04 01:54:22 PDT — before the fall-back (first occurrence of 01:xx AM)
is( time2str("%Z", 1352019262), "PDT",
"GH#10/RT#80649: pre-fall-back timestamp formats as PDT" );
# 2012-11-04 02:25:05 PST — after the repeated hour, clearly PST
is( time2str("%Z", 1352024705), "PST",
"GH#10/RT#80649: post-repeated-hour timestamp formats as PST" );
META.json 100644 000765 000024 62427 15157412057 14617 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 {
"abstract" : "Date and time formatting subroutines",
"author" : [
"Graham "
],
"dynamic_config" : 0,
"generated_by" : "Dist::Zilla version 6.033, CPAN::Meta::Converter version 2.150010",
"license" : [
"perl_5"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
"name" : "TimeDate",
"prereqs" : {
"configure" : {
"requires" : {
"ExtUtils::MakeMaker" : "0"
}
},
"develop" : {
"requires" : {
"File::Spec" : "0",
"IO::Handle" : "0",
"IPC::Open3" : "0",
"Test::CPAN::Meta" : "0",
"Test::MinimumVersion" : "0",
"Test::More" : "0.88",
"Test::NoTabs" : "0",
"Test::Pod" : "1.41",
"Test::Synopsis" : "0"
}
},
"runtime" : {
"requires" : {
"Carp" : "0"
}
},
"test" : {
"recommends" : {
"CPAN::Meta" : "2.120900"
},
"requires" : {
"ExtUtils::MakeMaker" : "0",
"File::Spec" : "0",
"Test::More" : "0"
}
}
},
"provides" : {
"Date::Format" : {
"file" : "lib/Date/Format.pm",
"version" : "2.35"
},
"Date::Format::Generic" : {
"file" : "lib/Date/Format/Generic.pm",
"version" : "2.35"
},
"Date::Language" : {
"file" : "lib/Date/Language.pm",
"version" : "2.35"
},
"Date::Language::Afar" : {
"file" : "lib/Date/Language/Afar.pm",
"version" : "2.35"
},
"Date::Language::Amharic" : {
"file" : "lib/Date/Language/Amharic.pm",
"version" : "2.35"
},
"Date::Language::Arabic" : {
"file" : "lib/Date/Language/Arabic.pm",
"version" : "2.35"
},
"Date::Language::Austrian" : {
"file" : "lib/Date/Language/Austrian.pm",
"version" : "2.35"
},
"Date::Language::Brazilian" : {
"file" : "lib/Date/Language/Brazilian.pm",
"version" : "2.35"
},
"Date::Language::Bulgarian" : {
"file" : "lib/Date/Language/Bulgarian.pm",
"version" : "2.35"
},
"Date::Language::Chinese" : {
"file" : "lib/Date/Language/Chinese.pm",
"version" : "2.35"
},
"Date::Language::Chinese_GB" : {
"file" : "lib/Date/Language/Chinese_GB.pm",
"version" : "2.35"
},
"Date::Language::Czech" : {
"file" : "lib/Date/Language/Czech.pm",
"version" : "2.35"
},
"Date::Language::Danish" : {
"file" : "lib/Date/Language/Danish.pm",
"version" : "2.35"
},
"Date::Language::Dutch" : {
"file" : "lib/Date/Language/Dutch.pm",
"version" : "2.35"
},
"Date::Language::English" : {
"file" : "lib/Date/Language/English.pm",
"version" : "2.35"
},
"Date::Language::Finnish" : {
"file" : "lib/Date/Language/Finnish.pm",
"version" : "2.35"
},
"Date::Language::French" : {
"file" : "lib/Date/Language/French.pm",
"version" : "2.35"
},
"Date::Language::Gedeo" : {
"file" : "lib/Date/Language/Gedeo.pm",
"version" : "2.35"
},
"Date::Language::German" : {
"file" : "lib/Date/Language/German.pm",
"version" : "2.35"
},
"Date::Language::Greek" : {
"file" : "lib/Date/Language/Greek.pm",
"version" : "2.35"
},
"Date::Language::Hungarian" : {
"file" : "lib/Date/Language/Hungarian.pm",
"version" : "2.35"
},
"Date::Language::Icelandic" : {
"file" : "lib/Date/Language/Icelandic.pm",
"version" : "2.35"
},
"Date::Language::Italian" : {
"file" : "lib/Date/Language/Italian.pm",
"version" : "2.35"
},
"Date::Language::Norwegian" : {
"file" : "lib/Date/Language/Norwegian.pm",
"version" : "2.35"
},
"Date::Language::Occitan" : {
"file" : "lib/Date/Language/Occitan.pm",
"version" : "2.35"
},
"Date::Language::Oromo" : {
"file" : "lib/Date/Language/Oromo.pm",
"version" : "2.35"
},
"Date::Language::Portuguese" : {
"file" : "lib/Date/Language/Portuguese.pm",
"version" : "2.35"
},
"Date::Language::Romanian" : {
"file" : "lib/Date/Language/Romanian.pm",
"version" : "2.35"
},
"Date::Language::Russian" : {
"file" : "lib/Date/Language/Russian.pm",
"version" : "2.35"
},
"Date::Language::Russian_cp1251" : {
"file" : "lib/Date/Language/Russian_cp1251.pm",
"version" : "2.35"
},
"Date::Language::Russian_koi8r" : {
"file" : "lib/Date/Language/Russian_koi8r.pm",
"version" : "2.35"
},
"Date::Language::Sidama" : {
"file" : "lib/Date/Language/Sidama.pm",
"version" : "2.35"
},
"Date::Language::Somali" : {
"file" : "lib/Date/Language/Somali.pm",
"version" : "2.35"
},
"Date::Language::Spanish" : {
"file" : "lib/Date/Language/Spanish.pm",
"version" : "2.35"
},
"Date::Language::Swedish" : {
"file" : "lib/Date/Language/Swedish.pm",
"version" : "2.35"
},
"Date::Language::Tigrinya" : {
"file" : "lib/Date/Language/Tigrinya.pm",
"version" : "2.35"
},
"Date::Language::TigrinyaEritrean" : {
"file" : "lib/Date/Language/TigrinyaEritrean.pm",
"version" : "2.35"
},
"Date::Language::TigrinyaEthiopian" : {
"file" : "lib/Date/Language/TigrinyaEthiopian.pm",
"version" : "2.35"
},
"Date::Language::Turkish" : {
"file" : "lib/Date/Language/Turkish.pm",
"version" : "2.35"
},
"Date::Parse" : {
"file" : "lib/Date/Parse.pm",
"version" : "2.35"
},
"Time::Zone" : {
"file" : "lib/Time/Zone.pm",
"version" : "2.35"
},
"TimeDate" : {
"file" : "lib/TimeDate.pm",
"version" : "2.35"
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/cpan-authors/TimeDate/issues"
},
"repository" : {
"type" : "git",
"url" : "https://github.com/cpan-authors/TimeDate.git",
"web" : "https://github.com/cpan-authors/TimeDate"
}
},
"version" : "2.35",
"x_Dist_Zilla" : {
"perl" : {
"version" : "5.038004"
},
"plugins" : [
{
"class" : "Dist::Zilla::Plugin::OurPkgVersion",
"name" : "OurPkgVersion",
"version" : "0.21"
},
{
"class" : "Dist::Zilla::Plugin::Test::Compile",
"config" : {
"Dist::Zilla::Plugin::Test::Compile" : {
"bail_out_on_fail" : 0,
"fail_on_warning" : "author",
"fake_home" : 0,
"filename" : "xt/author/00-compile.t",
"module_finder" : [
":InstallModules"
],
"needs_display" : 0,
"phase" : "develop",
"script_finder" : [
":PerlExecFiles"
],
"skips" : [],
"switch" : []
}
},
"name" : "Test::Compile",
"version" : "2.058"
},
{
"class" : "Dist::Zilla::Plugin::MetaTests",
"name" : "MetaTests",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Test::NoTabs",
"config" : {
"Dist::Zilla::Plugin::Test::NoTabs" : {
"filename" : "xt/author/no-tabs.t",
"finder" : [
":InstallModules",
":ExecFiles",
":TestFiles"
]
}
},
"name" : "Test::NoTabs",
"version" : "0.15"
},
{
"class" : "Dist::Zilla::Plugin::PodSyntaxTests",
"name" : "PodSyntaxTests",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
"name" : "Test::ReportPrereqs",
"version" : "0.029"
},
{
"class" : "Dist::Zilla::Plugin::PodWeaver",
"config" : {
"Dist::Zilla::Plugin::PodWeaver" : {
"finder" : [
":InstallModules",
":PerlExecFiles"
],
"plugins" : [
{
"class" : "Pod::Weaver::Plugin::EnsurePod5",
"name" : "@CorePrep/EnsurePod5",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Plugin::H1Nester",
"name" : "@CorePrep/H1Nester",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Plugin::SingleEncoding",
"name" : "@Default/SingleEncoding",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Name",
"name" : "@Default/Name",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Version",
"name" : "@Default/Version",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Region",
"name" : "@Default/prelude",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "SYNOPSIS",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "DESCRIPTION",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Generic",
"name" : "OVERVIEW",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "ATTRIBUTES",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "METHODS",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Collect",
"name" : "FUNCTIONS",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Leftovers",
"name" : "@Default/Leftovers",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Region",
"name" : "@Default/postlude",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Authors",
"name" : "@Default/Authors",
"version" : "4.020"
},
{
"class" : "Pod::Weaver::Section::Legal",
"name" : "@Default/Legal",
"version" : "4.020"
}
]
}
},
"name" : "PodWeaver",
"version" : "4.010"
},
{
"class" : "Dist::Zilla::Plugin::RunExtraTests",
"config" : {
"Dist::Zilla::Role::TestRunner" : {
"default_jobs" : 1
}
},
"name" : "RunExtraTests",
"version" : "0.029"
},
{
"class" : "Dist::Zilla::Plugin::MetaJSON",
"name" : "MetaJSON",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::MetaConfig",
"name" : "MetaConfig",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::MetaProvides::Package",
"config" : {
"Dist::Zilla::Plugin::MetaProvides::Package" : {
"finder_objects" : [
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM",
"version" : "6.033"
}
],
"include_underscores" : 0
},
"Dist::Zilla::Role::MetaProvider::Provider" : {
"$Dist::Zilla::Role::MetaProvider::Provider::VERSION" : "2.002004",
"inherit_missing" : 1,
"inherit_version" : 1,
"meta_noindex" : 1
},
"Dist::Zilla::Role::ModuleMetadata" : {
"Module::Metadata" : "1.000037",
"version" : "0.006"
}
},
"name" : "MetaProvides::Package",
"version" : "2.004003"
},
{
"class" : "Dist::Zilla::Plugin::NextRelease",
"name" : "NextRelease",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "runtime",
"type" : "requires"
}
},
"name" : "RuntimeRequires",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "test",
"type" : "requires"
}
},
"name" : "TestRequires",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::TestRelease",
"name" : "TestRelease",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Test::MinimumVersion",
"config" : {
"Dist::Zilla::Plugin::Test::MinimumVersion" : {
"max_target_perl" : "5.010"
}
},
"name" : "Test::MinimumVersion",
"version" : "2.000011"
},
{
"class" : "Dist::Zilla::Plugin::Git::Check",
"config" : {
"Dist::Zilla::Plugin::Git::Check" : {
"untracked_files" : "die"
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes",
"README.md",
"dist.ini"
],
"allow_dirty_match" : [],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.50.1 (Apple Git-155)",
"repo_root" : "."
}
},
"name" : "@Git/Check",
"version" : "2.051"
},
{
"class" : "Dist::Zilla::Plugin::Git::Commit",
"config" : {
"Dist::Zilla::Plugin::Git::Commit" : {
"add_files_in" : [
"Changes",
"README.md",
"dist.ini"
],
"commit_msg" : "v%V%n%n%c",
"signoff" : 0
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes",
"README.md",
"dist.ini"
],
"allow_dirty_match" : [],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.50.1 (Apple Git-155)",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Git/Commit",
"version" : "2.051"
},
{
"class" : "Dist::Zilla::Plugin::Git::Tag",
"config" : {
"Dist::Zilla::Plugin::Git::Tag" : {
"branch" : null,
"changelog" : "Changes",
"signed" : 0,
"tag" : "v2.35",
"tag_format" : "v%V",
"tag_message" : "v%V"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.50.1 (Apple Git-155)",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "@Git/Tag",
"version" : "2.051"
},
{
"class" : "Dist::Zilla::Plugin::Git::Push",
"config" : {
"Dist::Zilla::Plugin::Git::Push" : {
"push_to" : [
"origin",
"origin HEAD:refs/heads/released"
],
"remotes_must_exist" : 1
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.50.1 (Apple Git-155)",
"repo_root" : "."
}
},
"name" : "@Git/Push",
"version" : "2.051"
},
{
"class" : "Dist::Zilla::Plugin::Run::BeforeBuild",
"config" : {
"Dist::Zilla::Plugin::Run::Role::Runner" : {
"fatal_errors" : 1,
"quiet" : 0,
"version" : "0.050"
}
},
"name" : "Run::BeforeBuild",
"version" : "0.050"
},
{
"class" : "Dist::Zilla::Plugin::Run::AfterBuild",
"config" : {
"Dist::Zilla::Plugin::Run::Role::Runner" : {
"fatal_errors" : 1,
"quiet" : 0,
"run" : [
"cp %d/Makefile.PL ./",
"git status --porcelain | grep 'M Makefile.PL' && git commit -m 'Makefile.PL auto-updated by dist.ini' Makefile.PL && echo \"# Makefile.PL auto-update\" || echo \"# Makefile.PL up to date\""
],
"version" : "0.050"
}
},
"name" : "Run::AfterBuild",
"version" : "0.050"
},
{
"class" : "Dist::Zilla::Plugin::Git::NextVersion",
"config" : {
"Dist::Zilla::Plugin::Git::NextVersion" : {
"first_version" : "0.001",
"version_by_branch" : 0,
"version_regexp" : "(?^:^v(.+)$)"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.50.1 (Apple Git-155)",
"repo_root" : "."
}
},
"name" : "Git::NextVersion",
"version" : "2.051"
},
{
"class" : "Dist::Zilla::Plugin::PruneCruft",
"name" : "@Filter/PruneCruft",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::ManifestSkip",
"name" : "@Filter/ManifestSkip",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::MetaYAML",
"name" : "@Filter/MetaYAML",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::License",
"name" : "@Filter/License",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Readme",
"name" : "@Filter/Readme",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::ExecDir",
"name" : "@Filter/ExecDir",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::ShareDir",
"name" : "@Filter/ShareDir",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::MakeMaker",
"config" : {
"Dist::Zilla::Role::TestRunner" : {
"default_jobs" : 1
}
},
"name" : "@Filter/MakeMaker",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::Manifest",
"name" : "@Filter/Manifest",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::TestRelease",
"name" : "@Filter/TestRelease",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::ConfirmRelease",
"name" : "@Filter/ConfirmRelease",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::UploadToCPAN",
"name" : "@Filter/UploadToCPAN",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::GatherDir",
"config" : {
"Dist::Zilla::Plugin::GatherDir" : {
"exclude_filename" : [
"CLAUDE.md",
"Makefile.PL"
],
"exclude_match" : [],
"follow_symlinks" : 0,
"include_dotfiles" : 0,
"prefix" : "",
"prune_directory" : [],
"root" : "."
}
},
"name" : "GatherDir",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::MetaResources",
"name" : "MetaResources",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::PruneFiles",
"name" : "PruneFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::InsertExample",
"name" : "InsertExample",
"version" : "0.15"
},
{
"class" : "Dist::Zilla::Plugin::Test::Synopsis",
"name" : "Test::Synopsis",
"version" : "2.000007"
},
{
"class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
"config" : {
"Dist::Zilla::Role::FileWatcher" : {
"version" : "0.006"
}
},
"name" : "ReadmeAnyFromPod",
"version" : "0.163250"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":InstallModules",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":IncModules",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":TestFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExtraTestFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExecFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":PerlExecFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ShareFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":MainModule",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":AllFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":NoFiles",
"version" : "6.033"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : "MetaProvides::Package/AUTOVIV/:InstallModulesPM",
"version" : "6.033"
}
],
"zilla" : {
"class" : "Dist::Zilla::Dist::Builder",
"config" : {
"is_trial" : 0
},
"version" : "6.033"
}
},
"x_generated_by_perl" : "v5.38.4",
"x_serialization_backend" : "Cpanel::JSON::XS version 4.39",
"x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later"
}
format.t 100644 000765 000024 6411 15157412057 15065 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use Test::More tests => 292;
use Date::Format qw(ctime time2str);
use Date::Language;
use utf8;
my ($pkg, $t,$language);
$pkg = 'Date::Format::Generic';
while() {
chomp;
if (/^(\d+)/) {
$t = $1;
next;
}
elsif (/^(\w+)/) {
$language = $1;
$pkg = Date::Language->new($language);
next;
}
my($fmt,$res) = split(/\t+/,$_);
my $str = $pkg->time2str($fmt,$t,'GMT');
is($str, $res,"$fmt");
}
__DATA__
936709362 # Tue Sep 7 11:22:42 1999 GMT
%y 99
%Y 1999
%% %
%a Tue
%A Tuesday
%b Sep
%B September
%c 09/07/99 13:02:42
%C Tue Sep 7 13:02:42 GMT 1999
%d 07
%e 7
%D 09/07/99
%G 1026
%h Sep
%H 13
%I 01
%j 250
%k 13
%l 1
%L 9
%m 09
%M 02
%o 7th
%p PM
%q 3
%r 01:02:42 PM
%R 13:02
%s 936709362
%S 42
%T 13:02:42
%U 36
%w 2
%W 36
%x 09/07/99
%X 13:02:42
%y 99
%Y 1999
%Z GMT
%z +0000
%Od VII
%Oe VII
%OH XIII
%OI I
%Oj CCL
%Ok XIII
%Ol I
%Om IX
%OM II
%Oq III
%OY MCMXCIX
%Oy XCIX
German
%y 99
%Y 1999
%% %
%a Di
%A Dienstag
%b Sep
%B September
%c 09/07/99 13:02:42
%C Di Sep 7 13:02:42 GMT 1999
%d 07
%e 7
%D 09/07/99
%h Sep
%H 13
%I 01
%j 250
%k 13
%l 1
%L 9
%m 09
%M 02
%o 7.
%p PM
%q 3
%r 01:02:42 PM
%R 13:02
%s 936709362
%S 42
%T 13:02:42
%U 36
%w 2
%W 36
%x 09/07/99
%X 13:02:42
%y 99
%Y 1999
%Z GMT
%z +0000
%Od VII
%Oe VII
%OH XIII
%OI I
%Oj CCL
%Ok XIII
%Ol I
%Om IX
%OM II
%Oq III
%OY MCMXCIX
%Oy XCIX
French
%y 99
%Y 1999
%% %
%a mar
%A mardi
%b sep
%B septembre
%c 09/07/99 13:02:42
%C mar sep 7 13:02:42 GMT 1999
%d 07
%e 7
%D 09/07/99
%h sep
%H 13
%I 01
%j 250
%k 13
%l 1
%L 9
%m 09
%M 02
%o 7e
%p PM
%q 3
%r 01:02:42 PM
%R 13:02
%s 936709362
%S 42
%T 13:02:42
%U 36
%w 2
%W 36
%x 09/07/99
%X 13:02:42
%y 99
%Y 1999
%Z GMT
%z +0000
915192000 # Fri Jan 1 12:00:00 1999 GMT
%o 1er
%A vendredi
936709362 # Tue Sep 7 11:22:42 1999 GMT
Italian
%y 99
%Y 1999
%% %
%a Mar
%A Martedi
%b Set
%B Settembre
%c 09/07/99 13:02:42
%C Mar Set 7 13:02:42 GMT 1999
%d 07
%e 7
%D 09/07/99
%h Set
%H 13
%I 01
%j 250
%k 13
%l 1
%L 9
%m 09
%M 02
%o 7th
%p PM
%q 3
%r 01:02:42 PM
%R 13:02
%s 936709362
%S 42
%T 13:02:42
%U 36
%w 2
%W 36
%x 09/07/99
%X 13:02:42
%y 99
%Y 1999
%Z GMT
%z +0000
%Od VII
%Oe VII
%OH XIII
%OI I
%Oj CCL
%Ok XIII
%Ol I
%Om IX
%OM II
%Oq III
%OY MCMXCIX
%Oy XCIX
316648800 # Wed Jan 14 00:00:00 1980
%G 1 #0 is interpreted as empty string
Bulgarian
1283926923 # ср сеп 8 09:22:03 EET 2010 /Tue Sep 06:22:03 GMT 2010
%y 10
%Y 2010
%% %
%a ср
%A сряда
%b сеп
%B септември
%c 09/08/10 06:22:03
%C ср сеп 8 06:22:03 GMT 2010
%d 08
%e 8
%D 09/08/10
%G 1600
%h сеп
%H 06
%I 06
%j 251
%k 6
%l 6
%L 9
%m 09
%M 22
%o 8ми
%p AM
%q 3
%r 06:22:03 AM
%R 06:22
%s 1283926923
%S 03
%T 06:22:03
%U 36
%w 3
%W 36
%x 09/08/10
%X 06:22:03
%Z GMT
%z +0000
%z +0000
%Od VIII
%Oe VIII
%OH VI
%OI VI
%Oj CCLI
%Ok VI
%Ol VI
%Om IX
%OM XXII
%Oq III
%OY MMX
%Oy X
936709362 # Tue Sep 7 13:02:42 1999 GMT
Portuguese
%y 99
%Y 1999
%% %
%a ter
%A terça-feira
%b set
%B setembro
%c 09/07/99 13:02:42
%C ter set 7 13:02:42 GMT 1999
%d 07
%e 7
%D 09/07/99
%h set
%H 13
%I 01
%j 250
%k 13
%l 1
%L 9
%m 09
%M 02
%o 7º
%p PM
%q 3
%r 01:02:42 PM
%R 13:02
%s 936709362
%S 42
%T 13:02:42
%U 36
%w 2
%W 36
%x 09/07/99
%X 13:02:42
%y 99
%Y 1999
%Z GMT
%z +0000
%Od VII
%Oe VII
%OH XIII
%OI I
%Oj CCL
%Ok XIII
%Ol I
%Om IX
%OM II
%Oq III
%OY MCMXCIX
%Oy XCIX
msk-tz.t 100644 000765 000024 1122 15157412057 15014 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 2;
use Date::Parse qw(str2time);
use Time::Zone;
# RT#81350: MSK (Moscow Standard Time) offset
# Russia was UTC+4 in 2011-2014 (permanent DST), but reverted to UTC+3 in October 2014.
# The correct current offset is UTC+3 = 10800 seconds.
{
my $offset = tz_offset("MSK");
is($offset, 10800, "RT#81350: tz_offset('MSK') returns 10800 (UTC+3)");
my $time = str2time("2024-01-15 12:00:00 MSK");
my $time_utc = str2time("2024-01-15 09:00:00 UTC");
is($time, $time_utc, "RT#81350: MSK date parses to correct UTC equivalent");
}
Makefile.PL 100644 000765 000024 2057 15157412057 15121 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 # This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.033.
use strict;
use warnings;
use ExtUtils::MakeMaker;
my %WriteMakefileArgs = (
"ABSTRACT" => "Date and time formatting subroutines",
"AUTHOR" => "Graham ",
"CONFIGURE_REQUIRES" => {
"ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "TimeDate",
"LICENSE" => "perl",
"NAME" => "TimeDate",
"PREREQ_PM" => {
"Carp" => 0
},
"TEST_REQUIRES" => {
"ExtUtils::MakeMaker" => 0,
"File::Spec" => 0,
"Test::More" => 0
},
"VERSION" => "2.35",
"test" => {
"TESTS" => "t/*.t"
}
);
my %FallbackPrereqs = (
"Carp" => 0,
"ExtUtils::MakeMaker" => 0,
"File::Spec" => 0,
"Test::More" => 0
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
SECURITY.md 100644 000765 000024 2470 15157412057 14737 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35 # Security Policy
## Supported Versions
Only the latest released version of TimeDate receives security fixes.
| Version | Supported |
| ------- | --------- |
| latest | Yes |
| older | No |
## Reporting a Vulnerability
TimeDate handles date/time string parsing and may be used to process untrusted
input. If you discover a security vulnerability, **please do not report it
publicly** via a GitHub issue.
Instead, report it privately using one of these methods:
- **GitHub private vulnerability reporting**: use the
[Security Advisory](https://github.com/cpan-authors/TimeDate/security/advisories/new)
form on GitHub (preferred).
- **Email**: contact the maintainer directly. You can find contact details on
the [CPAN author page for ATOOMIC](https://metacpan.org/author/ATOOMIC).
Please include as much detail as possible:
- A description of the vulnerability
- Steps to reproduce or a minimal proof-of-concept
- The potential impact
## Disclosure Policy
- We will acknowledge receipt of your report within **5 business days**.
- We aim to provide an assessment and a fix timeline within **14 days**.
- We will coordinate public disclosure with you after a fix is available.
This project follows the guidelines described at
.
rt52387.t 100644 000765 000024 1416 15157412057 14633 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 5;
use Date::Format qw(time2str strftime);
# RT#52387: seconds since the Epoch, UCT
{
my $time = time;
my @lt = localtime($time);
is(strftime("%s", @lt), $time, "RT#52387: strftime %s returns epoch");
is(time2str("%s", $time), $time, "RT#52387: time2str %s returns epoch");
# strftime %s with explicit timezone must still return the same epoch —
# %s is timezone-agnostic (Unix timestamp is always UTC-based).
is(strftime("%s", @lt, "UTC"), $time, "RT#52387: strftime %s with UTC tz returns epoch");
is(strftime("%s", @lt, "+0000"), $time, "RT#52387: strftime %s with +0000 tz returns epoch");
is(strftime("%s", @lt, "+0100"), $time, "RT#52387: strftime %s with +0100 tz returns epoch");
}
tz-lang.t 100644 000765 000024 3023 15157412057 15145 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use Test::More tests => 10;
use Date::Language;
# Tests for language-specific timezone abbreviation translation (issue #1 / RT#52878)
# When using %Z format with a language object, timezone abbreviations should be
# translated to the language's local equivalents if the language defines a %TZ mapping.
my $german = Date::Language->new('German');
my $english = Date::Language->new('English');
# Fixed timestamp: 2009-01-01 00:00:00 UTC (standard time, no DST)
my $t = 1230768000;
# English should return standard English abbreviations unchanged
is( $english->time2str('%Z', $t, 'CET'), 'CET', 'English: CET stays CET' );
is( $english->time2str('%Z', $t, 'CEST'), 'CEST', 'English: CEST stays CEST' );
is( $english->time2str('%Z', $t, 'GMT'), 'GMT', 'English: GMT stays GMT' );
# German should translate CET → MEZ and CEST → MESZ
is( $german->time2str('%Z', $t, 'CET'), 'MEZ', 'German: CET → MEZ' );
is( $german->time2str('%Z', $t, 'CEST'), 'MESZ', 'German: CEST → MESZ' );
# German: timezones without a translation should pass through unchanged
is( $german->time2str('%Z', $t, 'GMT'), 'GMT', 'German: GMT passes through (no translation defined)' );
is( $german->time2str('%Z', $t, 'UTC'), 'UTC', 'German: UTC passes through (no translation defined)' );
# German: other European timezone translations
is( $german->time2str('%Z', $t, 'EET'), 'OEZ', 'German: EET → OEZ' );
is( $german->time2str('%Z', $t, 'EEST'), 'OESZ', 'German: EEST → OESZ' );
is( $german->time2str('%Z', $t, 'WET'), 'WEZ', 'German: WET → WEZ' );
rt57800.t 100644 000765 000024 2455 15157412057 14632 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 4;
use Date::Parse qw(str2time);
# RT#57800 (GH#3): str2time fails on numeric m/d/yyyy dates before 1970
# str2time('5/1/1960') was returning undef with "Day too big" errors on
# 32-bit systems. Root cause: strptime extracts the 2-digit year (60) and
# stores century (19) separately. str2time must reconstruct the full 4-digit
# year before calling Time::Local to avoid the 2-digit year windowing heuristic
# mapping year 60 to 2060 instead of 1960.
{
my @cases = (
[ '5/1/1960', 1960, 5, 1, "m/d/yyyy May 1 1960" ],
[ '1/5/1960', 1960, 1, 5, "m/d/yyyy Jan 5 1960" ],
[ '12/31/1960', 1960, 12, 31, "m/d/yyyy Dec 31 1960" ],
[ '5/1/1901', 1901, 5, 1, "m/d/yyyy May 1 1901" ],
);
for my $c (@cases) {
my ($date, $expected_year, $expected_mon, $expected_day, $desc) = @$c;
SKIP: {
skip "pre-1970 dates on Win32", 1 if $^O eq 'MSWin32';
my $t = str2time($date);
if (!defined $t) {
fail("RT#57800: str2time('$date') returned undef");
next;
}
my @gm = gmtime($t);
my $got_year = 1900 + $gm[5];
is($got_year, $expected_year, "RT#57800: $desc parses to year $expected_year");
}
}
}
getdate.t 100644 000765 000024 17170 15157412057 15236 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Parse;
my @data = split /\n/, <<'DATA';
1995-01-24 ;790905600
1995-06-24 ;803952000
92/01/02 12:01 ;694353660
92/01/02 12:01 AM ;694310460
92/01/02 12:01 PM ;694353660
2002-11-02 11pm GMT ;1036278000
2002-11-02 11 pm GMT ;1036278000
1995-01-24 GMT ;790905600
1995-01-24 BST ;790902000
1995-06-24 GMT ;803952000
1995-06-24 BST ;803948400
1992-1-2 12:01 GMT ;694353660
1992-1-2-12:01:00 GMT ;694353660
Wed, 16 Jun 94 07:29:35 CST ;771773375
Wed,16 Jun 94 07:29:35 CST ;771773375
Wed, 16 Nov 94 07:29:35 CST ;784992575
Mon, 21 Nov 94 07:42:23 CST ;785425343
Mon, 21 Nov 94 04:28:18 CST ;785413698
Tue, 15 Nov 94 09:15:10 GMT ;784890910
Wed, 16 Nov 94 09:39:49 GMT ;784978789
Wed, 16 Nov 94 09:23:17 GMT ;784977797
Wed, 16 Nov 94 12:39:49 GMT ;784989589
Wed, 16 Nov 94 14:03:06 GMT ;784994586
Wed, 16 Nov 94 05:30:51 CST ;784985451
Thu, 17 Nov 94 03:19:30 CST ;785063970
1994:11:21T14:05:32+0000 ;785426732
Mon, 21 Nov 94 14:05:32 GMT ;785426732
Mon, 14 Nov 94 15:08:49 CST ;784847329
Wed, 16 Nov 94 14:48:06 GMT ;784997286
Thu, 17 Nov 94 14:22:03 GMT ;785082123
Wed, 16 Nov 94 14:36:00 GMT ;784996560
Wed, 16 Nov 94 09:23:17 GMT ;784977797
Wed, 16 Nov 94 10:01:43 GMT ;784980103
Wed, 16 Nov 94 15:03:35 GMT ;784998215
Mon, 21 Nov 94 13:55:19 GMT ;785426119
Wed, 16 Nov 94 08:46:11 CST ;784997171
Wed, 9 Nov 1994 09:50:32 -0500 (EST) ;784392632
Thu, 13 Oct 94 10:13:13 -0700 ;782068393
Sat, 19 Nov 1994 16:59:14 +0100 ;785260754
Thu, 3 Nov 94 14:10:47 EST ;783889847
Thu, 3 Nov 94 21:51:09 EST ;783917469
Fri, 4 Nov 94 9:24:52 EST ;783959092
Wed, 9 Nov 94 09:38:54 EST ;784391934
Mon, 14 Nov 94 13:20:12 EST ;784837212
Wed, 16 Nov 94 17:09:13 EST ;785023753
Tue, 15 Nov 94 12:27:01 PST ;784931221
Fri, 18 Nov 1994 07:34:05 -0600 ;785165645
Mon, 21 Nov 94 14:34:28 -0500 ;785446468
Fri, 18 Nov 1994 12:05:47 -0800 (PST);785189147
Fri, 18 Nov 1994 12:36:26 -0800 (PST);785190986
Wed, 16 Nov 1994 15:58:58 GMT ;785001538
Sun, 06 Nov 94 14:27:40 -0500 ;784150060
Mon, 07 Nov 94 08:20:13 -0500 ;784214413
Mon, 07 Nov 94 16:48:42 -0500 ;784244922
Wed, 09 Nov 94 15:46:16 -0500 ;784413976
Sun, 6 Nov 1994 02:38:17 -0800 ;784118297
Tue, 1 Nov 1994 13:53:49 -0500 ;783716029
Tue, 15 Nov 94 08:31:59 +0100 ;784884719
Sun, 6 Nov 1994 11:09:12 -0500 (IST) ;784138152
Fri, 4 Nov 94 12:52:10 EST ;783971530
Mon, 31 Oct 1994 14:17:39 -0500 (EST);783631059
Mon, 14 Nov 94 11:25:00 CST ;784833900
Mon, 14 Nov 94 13:26:29 CST ;784841189
Fri, 18 Nov 94 8:42:47 CST ;785169767
Thu, 17 Nov 94 14:32:01 +0900 ;785050321
Wed, 2 Nov 94 18:16:31 +0100 ;783796591
Fri, 18 Nov 94 10:46:26 +0100 ;785151986
Tue, 8 Nov 1994 22:39:28 +0200 ;784327168
Wed, 16 Nov 1994 10:01:08 -0500 (EST);784998068
Wed, 2 Nov 1994 16:59:42 -0800 ;783824382
Wed, 9 Nov 94 10:00:23 PST ;784404023
Fri, 18 Nov 94 17:01:43 PST ;785206903
Mon, 14 Nov 1994 14:47:46 -0500 ;784842466
Mon, 21 Nov 1994 04:56:04 -0500 (EST);785411764
Mon, 21 Nov 1994 11:50:12 -0800 ;785447412
Sat, 5 Nov 1994 14:04:16 -0600 (CST) ;784065856
Sat, 05 Nov 94 13:10:13 MST ;784066213
Wed, 02 Nov 94 10:47:48 -0800 ;783802068
Wed, 02 Nov 94 13:19:15 -0800 ;783811155
Thu, 03 Nov 94 15:27:07 -0800 ;783905227
Fri, 04 Nov 94 09:12:12 -0800 ;783969132
Wed, 9 Nov 1994 10:13:03 +0000 (GMT) ;784375983
Wed, 9 Nov 1994 15:28:37 +0000 (GMT) ;784394917
Wed, 2 Nov 1994 17:37:41 +0100 (MET) ;783794261
05 Nov 94 14:22:19 PST ;784074139
16 Nov 94 22:28:20 PST ;785053700
Tue, 1 Nov 1994 19:51:15 -0800 ;783748275
Wed, 2 Nov 94 12:21:23 GMT ;783778883
Fri, 18 Nov 94 18:07:03 GMT ;785182023
Wed, 16 Nov 1994 11:26:27 -0500 ;785003187
Sun, 6 Nov 1994 13:48:49 -0500 ;784147729
Tue, 8 Nov 1994 13:19:37 -0800 ;784329577
Fri, 18 Nov 1994 11:01:12 -0800 ;785185272
Mon, 21 Nov 1994 00:47:58 -0500 ;785396878
Mon, 7 Nov 1994 14:22:48 -0800 (PST) ;784246968
Wed, 16 Nov 1994 15:56:45 -0800 (PST);785030205
Thu, 3 Nov 1994 13:17:47 +0000 ;783868667
Wed, 9 Nov 1994 17:32:50 -0500 (EST) ;784420370
Wed, 9 Nov 94 16:31:52 PST ;784427512
Wed, 09 Nov 94 10:41:10 -0800 ;784406470
Wed, 9 Nov 94 08:42:22 MST ;784395742
Mon, 14 Nov 1994 08:32:13 -0800 ;784830733
Mon, 14 Nov 1994 11:34:32 -0500 (EST);784830872
Mon, 14 Nov 94 16:48:09 GMT ;784831689
Tue, 15 Nov 1994 10:27:33 +0000 ;784895253
Wed, 02 Nov 94 13:56:54 MST ;783809814
Thu, 03 Nov 94 15:24:45 MST ;783901485
Thu, 3 Nov 1994 15:13:53 -0700 (MST) ;783900833
Fri, 04 Nov 94 08:15:13 MST ;783962113
Thu, 3 Nov 94 18:15:47 EST ;783904547
Tue, 08 Nov 94 07:02:33 MST ;784303353
Thu, 3 Nov 94 18:15:47 EST ;783904547
Tue, 15 Nov 94 07:26:05 MST ;784909565
Wed, 2 Nov 1994 00:00:55 -0600 (CST) ;783756055
Sun, 6 Nov 1994 01:19:13 -0600 (CST) ;784106353
Mon, 7 Nov 1994 23:16:57 -0600 (CST) ;784271817
Tue, 08 Nov 1994 13:21:21 -0600 ;784322481
Mon, 07 Nov 94 13:47:37 PST ;784244857
Tue, 08 Nov 94 11:23:19 PST ;784322599
Tue, 01 Nov 1994 11:28:25 -0800 ;783718105
Tue, 15 Nov 1994 13:11:47 -0800 ;784933907
Tue, 15 Nov 1994 13:18:38 -0800 ;784934318
Tue, 15 Nov 1994 0:18:38 -0800 ;784887518
Jul 13 1999 1:23P GMT ;931872180
Jul 13 1999 1:23P.M GMT ;931872180
Jul 13 1999 1:23P.M. GMT ;931872180
Jul-13-1999 1:23P.M GMT ;931872180
Jul/13/1999 1:23P.M. GMT ;931872180
2001-02-26T13:44:12-0700 ;983220252
2001-02-26T13:44-0700 ;983220240
2001-02-26T13-0700 ;983217600
2001-02-26T13-44-12-0700 ;983220252
2001-02-26T13-44-0700 ;983220240
2001-02-26T13-0700 ;983217600
07/Nov/2000:16:45:56 +0100 ;973611956
2002-11-07T23:31:49-05:00 ;1036729909
2003-02-17T07:45:56Z ;1045467956
2003-02-17T08:14:07.198189+0000 ;1045469647.198189
20020722T100000Z ;1027332000
Jul 22 10:00:00 UTC 2002 ;1027332000
2002-07-22 10:00:00Z ;1027332000
2002-07-22 10:00:00 Z ;1027332000
2002-07-22 10:00 Z ;1027332000
2002-07-22 10:00Z ;1027332000
2002-07-22 10:00 +100 ;1027328400
2002-07-22 10:00 +0100 ;1027328400
DATA
require Time::Local;
my $offset = Time::Local::timegm(0, 0, 0, 1, 0, 1970);
my $loop = 0;
for my $line (@data) {
$loop++;
my ($str, $time_expect) = split ';', $line;
my $time = Date::Parse::str2time($str);
if ($loop < 6) {
# The first five tests are parsed in the current time zone
# But the check number is in GMT
my @lt = localtime($time_expect);
my @gt = gmtime($time_expect);
my $tzsec = ($gt[1] - $lt[1]) * 60 + ($gt[2] - $lt[2]) * 3600;
my ($lday, $gday) = ($lt[7], $gt[7]);
if ($lt[5] > $gt[5]) {
$tzsec -= 24 * 3600;
}
elsif ($gt[5] > $lt[5]) {
$tzsec += 24 * 3600;
}
else {
$tzsec += ($gt[7] - $lt[7]) * (24 * 3600);
}
$time -= $tzsec;
}
$time_expect += $offset;
is($time, $time_expect, "parse: $str");
}
done_testing;
rt106105.t 100644 000765 000024 2223 15157412057 14674 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 6;
use Date::Parse qw(strptime);
# RT#106105: Date::Parse inconsistent year handling for years before 1901
# strptime() must return year as offset from 1900 consistently, regardless of
# whether the year is before or after 1900. Previously, years <= 1900 were
# returned as the full 4-digit year rather than (year - 1900).
{
# 1901: already worked — year=1, century=19
my @t1901 = strptime('1 Jan 1901 12:00');
is($t1901[5], 1, "RT#106105: strptime year field is 1 for 1901 (offset from 1900)");
is($t1901[7], 19, "RT#106105: strptime century field is 19 for 1901");
# 1900: boundary — year=0, century=19
my @t1900 = strptime('1 Jan 1900 12:00');
is($t1900[5], 0, "RT#106105: strptime year field is 0 for 1900 (offset from 1900)");
is($t1900[7], 19, "RT#106105: strptime century field is 19 for 1900");
# 1899: previously broken — returned 1899 instead of -1
my @t1899 = strptime('1 Jan 1899 12:00');
is($t1899[5], -1, "RT#106105: strptime year field is -1 for 1899 (offset from 1900)");
is($t1899[7], 18, "RT#106105: strptime century field is 18 for 1899");
}
rt-parse.t 100644 000765 000024 2511 15157412057 15327 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 5;
use Date::Parse qw(strptime str2time);
# RT#48164: Date::Parse unable to set seconds correctly
{
for my $str ("2008.11.30 22:35 CET", "2008-11-30 22:35 CET") {
my @t = strptime($str);
my $t = join ":", map { defined($_) ? $_ : "-" } @t;
is($t, "-:35:22:30:10:108:3600:20", "RT#48164: seconds parsing for '$str'");
}
}
# RT#17396: Parse error for french date with 'mars' (march) as month
{
use Date::Language;
my $dateP = Date::Language->new('French');
my $timestamp = $dateP->str2time('4 mars 2005');
my ($ss, $mm, $hh, $day, $month, $year, $zone) = localtime $timestamp;
$month++;
$year += 1900;
my $date = "$day/$month/$year";
is($date, "4/3/2005", "RT#17396: French 'mars' parsed correctly");
}
# RT#51664: Change in str2time behaviour between 1.16 and 1.19
{
ok(str2time('16 Oct 09') >= 0, "RT#51664: '16 Oct 09' parses to non-negative time");
}
# RT#84075: Date::Parse::str2time maps date in 1963 to 2063
{
my $this_year = 1900 + (gmtime(time))[5];
my $target_year = $this_year - 50;
my $date = "$target_year-01-01 00:00:00 UTC";
my $time = str2time($date);
my $year_parsed_as = 1900 + (gmtime($time))[5];
is($year_parsed_as, $target_year, "RT#84075: year $target_year not mapped to future");
}
pod-valid.t 100644 000765 000024 664 15157412057 15440 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
BEGIN {
eval { require Pod::Checker; 1 }
or plan skip_all => 'Pod::Checker not available';
}
plan tests => 1;
# RT#53557: Missing =back in Date::Parse POD before =head1 MULTI-LANGUAGE SUPPORT
{
my $checker = Pod::Checker->new;
$checker->parse_from_file('lib/Date/Parse.pm');
is($checker->num_errors, 0, "RT#53557: Date::Parse.pm has valid POD (no missing =back)");
}
rt-format.t 100644 000765 000024 524 15157412057 15467 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 2;
use Date::Format qw(time2str);
# RT#45067: Date::Format with %z gives wrong results for half-hour timezones
{
for my $zone (qw(-0430 -0745)) {
my $zone_str = time2str("%Z %z", time, $zone);
is($zone_str, "$zone $zone", "RT#45067: half-hour timezone $zone");
}
}
lang-data.t 100644 000765 000024 24445 15157412057 15454 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Language;
# Tue Sep 7 13:02:42 1999 GMT
# wday=2 (Tuesday), mon=8 (September, 0-indexed)
my $time = 936709362;
# Expected values for %A (full day), %a (short day), %B (full month), %b (short month)
# extracted from each language module's @DoW[2], @DoWs[2], @MoY[8], @MoYs[8]
my %expected = (
Afar => { A => "Talaata", a => "Tal", B => "Waysu", b => "Way" },
Amharic => { A => "\x{121b}\x{12ad}\x{1230}\x{129e}", a => "\x{121b}\x{12ad}\x{1230}", B => "\x{1234}\x{1355}\x{1274}\x{121d}\x{1260}\x{122d}", b => "\x{1234}\x{1355}\x{1274}" },
Arabic => { A => "\x{627}\x{644}\x{62b}\x{644}\x{627}\x{62b}\x{627}\x{621}", a => "\x{627}\x{644}\x{62b}", B => "\x{633}\x{628}\x{62a}\x{645}\x{628}\x{631}", b => "\x{633}\x{628}\x{62a}" },
Austrian => { A => "Dienstag", a => "Di", B => "September", b => "Sep" },
Brazilian => { A => "Ter\x{e7}a", a => "Ter", B => "Setembro", b => "Set" },
Bulgarian => { A => "\x{432}\x{442}\x{43e}\x{440}\x{43d}\x{438}\x{43a}", a => "\x{432}\x{442}", B => "\x{441}\x{435}\x{43f}\x{442}\x{435}\x{43c}\x{432}\x{440}\x{438}", b => "\x{441}\x{435}\x{43f}" },
Chinese => { A => "\x{661f}\x{671f}\x{4e8c}", a => "\x{661f}\x{671f}\x{4e8c}", B => "\x{4e5d}\x{6708}", b => "\x{4e5d}\x{6708}" },
Chinese_GB => { A => "\x{d0}\x{c7}\x{c6}\x{da}\x{b6}\x{fe}", a => "\x{d0}\x{c7}\x{c6}\x{da}\x{b6}\x{fe}", B => "\x{be}\x{c5}\x{d4}\x{c2}", b => "\x{be}\x{c5}\x{d4}\x{c2}" },
Czech => { A => "\x{fa}ter\x{fd}", a => "\x{da}t", B => "z\x{e1}\x{f8}\x{ed}", b => "z\x{e1}\x{f8}\x{ed}" },
Danish => { A => "Tirsdag", a => "Tir", B => "September", b => "Sep" },
Dutch => { A => "dinsdag", a => "di", B => "september", b => "sep" },
English => { A => "Tuesday", a => "Tue", B => "September", b => "Sep" },
Finnish => { A => "tiistai", a => "tiistai", B => "syyskuu", b => "syyskuu" },
French => { A => "mardi", a => "mar", B => "septembre", b => "sep" },
Gedeo => { A => "Masano", a => "Mas", B => "Canissa", b => "Can" },
German => { A => "Dienstag", a => "Di", B => "September", b => "Sep" },
Greek => { A => "\x{3a4}\x{3c1}\x{3af}\x{3c4}\x{3b7}", a => "\x{3a4}\x{3c1}", B => "\x{3a3}\x{3b5}\x{3c0}\x{3c4}\x{3b5}\x{3bc}\x{3c4}\x{3bf}\x{3c5}", b => "\x{3a3}\x{3b5}\x{3c0}" },
Hungarian => { A => "Kedd", a => "Ked", B => "Szeptember", b => "Sze" },
Icelandic => { A => "\x{de}ri\x{f0}judagur", a => "\x{de}ri", B => "September", b => "Sep" },
Italian => { A => "Martedi", a => "Mar", B => "Settembre", b => "Set" },
Norwegian => { A => "Tirsdag", a => "Tir", B => "September", b => "Sep" },
Occitan => { A => "dimars", a => "dim", B => "setembre", b => "set" },
Portuguese => { A => "ter\x{e7}a-feira", a => "ter", B => "setembro", b => "set" },
Oromo => { A => "Qibxata", a => "Qib", B => "Fuulbana", b => "Fuu" },
Romanian => { A => "marti", a => "mar", B => "septembrie", b => "sep" },
Russian => { A => "\x{f3}\x{d2}\x{c5}\x{c4}\x{c1}", a => "\x{f3}\x{d2}", B => "\x{f3}\x{c5}\x{ce}\x{d4}\x{d1}\x{c2}\x{d2}\x{d1}", b => "\x{f3}\x{c5}\x{ce}" },
Russian_cp1251 => { A => "\x{c2}\x{f2}\x{ee}\x{f0}\x{ed}\x{e8}\x{ea}", a => "\x{c2}\x{f2}\x{f0}", B => "\x{d1}\x{e5}\x{ed}\x{f2}\x{ff}\x{e1}\x{f0}\x{fc}", b => "\x{d1}\x{e5}\x{ed}" },
Russian_koi8r => { A => "\x{f7}\x{d4}\x{cf}\x{d2}\x{ce}\x{c9}\x{cb}", a => "\x{f7}\x{d4}\x{d2}", B => "\x{f3}\x{c5}\x{ce}\x{d4}\x{d1}\x{c2}\x{d2}\x{d8}", b => "\x{f3}\x{c5}\x{ce}" },
Sidama => { A => "Maakisanyo", a => "Maa", B => "September", b => "Sep" },
Somali => { A => "Salaaso", a => "Sal", B => "Bisha Sagaalaad", b => "Sag" },
Spanish => { A => "martes", a => "mar", B => "septiembre", b => "sep" },
Swedish => { A => "tisdagen", a => "ti", B => "september", b => "sep" },
Tigrinya => { A => "\x{1230}\x{1209}\x{1235}", a => "\x{1230}\x{1209}\x{1235}", B => "\x{1234}\x{1355}\x{1274}\x{121d}\x{1260}\x{122d}", b => "\x{1234}\x{1355}\x{1274}" },
TigrinyaEritrean => { A => "\x{1230}\x{1209}\x{1235}", a => "\x{1230}\x{1209}\x{1235}", B => "\x{1234}\x{1355}\x{1274}\x{121d}\x{1260}\x{122d}", b => "\x{1234}\x{1355}\x{1274}" },
TigrinyaEthiopian => { A => "\x{1230}\x{1209}\x{1235}", a => "\x{1230}\x{1209}\x{1235}", B => "\x{1234}\x{1355}\x{1274}\x{121d}\x{1260}\x{122d}", b => "\x{1234}\x{1355}\x{1274}" },
Turkish => { A => "Sal\x{131}", a => "Sal", B => "Eyl\x{fc}l", b => "Eyl" },
);
for my $lang (sort keys %expected) {
my $l = Date::Language->new($lang);
my $e = $expected{$lang};
# Content checks
is($l->time2str('%A', $time, 'GMT'), $e->{A}, "$lang: full day name (%A)");
is($l->time2str('%a', $time, 'GMT'), $e->{a}, "$lang: short day name (%a)");
is($l->time2str('%B', $time, 'GMT'), $e->{B}, "$lang: full month name (%B)");
is($l->time2str('%b', $time, 'GMT'), $e->{b}, "$lang: short month name (%b)");
# Structural checks
no strict 'refs';
my $pkg = "Date::Language::$lang";
is(scalar @{"${pkg}::DoW"}, 7, "$lang: 7 day names");
is(scalar @{"${pkg}::DoWs"}, 7, "$lang: 7 short day names");
is(scalar @{"${pkg}::MoY"}, 12, "$lang: 12 month names");
is(scalar @{"${pkg}::MoYs"}, 12, "$lang: 12 short month names");
is(scalar @{"${pkg}::AMPM"}, 2, "$lang: 2 AM/PM entries");
}
done_testing;
edge-cases.t 100644 000765 000024 21666 15157412057 15626 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Parse qw(str2time strptime);
use Date::Language;
# --- Undef / empty / garbage inputs ---
ok(!defined str2time(undef), "str2time(undef) returns undef");
ok(!defined str2time(""), "str2time('') returns undef");
ok(!defined str2time("garbage"), "str2time('garbage') returns undef");
ok(!defined str2time("not a date at all"), "str2time('not a date at all') returns undef");
# --- ISO 8601 variants ---
{
my $t1 = str2time("2002-07-22T10:00:00Z");
ok(defined $t1, "ISO 8601 with T separator and Z");
is($t1, 1027332000, "ISO 8601 basic format parses correctly");
my $t2 = str2time("2002-07-22 10:00:00Z");
is($t2, 1027332000, "ISO 8601 with space separator and Z");
my $t3 = str2time("20020722T100000Z");
is($t3, 1027332000, "ISO 8601 compact format");
my $t4 = str2time("2001-02-26T13:44:12-0700");
is($t4, 983220252, "ISO 8601 with negative offset");
my $t5 = str2time("2002-11-07T23:31:49-05:00");
is($t5, 1036729909, "RFC 3339 with colon in offset");
}
# --- AM/PM parsing ---
{
my $base = str2time("Jul 13 1999 13:23:00 GMT");
is(str2time("Jul 13 1999 1:23P GMT"), $base, "1:23P parses as PM");
is(str2time("Jul 13 1999 1:23P.M GMT"), $base, "1:23P.M parses as PM");
is(str2time("Jul 13 1999 1:23P.M. GMT"), $base, "1:23P.M. parses as PM");
my $am = str2time("92/01/02 12:01 AM");
my $pm = str2time("92/01/02 12:01 PM");
ok(defined $am && defined $pm, "AM/PM dates parse");
cmp_ok($pm - $am, '==', 12 * 3600, "PM is 12 hours after AM");
}
# --- Fractional seconds ---
{
my $t = str2time("2003-02-17T08:14:07.198189+0000");
ok(defined $t, "fractional seconds parse");
cmp_ok(abs($t - 1045469647.198189), '<', 0.001, "fractional seconds preserved");
my $t2 = str2time("1995-01-24T09:08:17.1823213");
ok(defined $t2, "high-precision fractional seconds parse");
}
# --- Apache-style dates ---
{
my $t = str2time("07/Nov/2000:16:45:56 +0100");
is($t, 973611956, "Apache log date format");
}
# --- RFC 2822 / email dates ---
{
my $t = str2time("Wed, 9 Nov 1994 09:50:32 -0500 (EST)");
is($t, 784392632, "RFC 2822 date with comment");
my $t2 = str2time("Sat, 19 Nov 1994 16:59:14 +0100");
is($t2, 785260754, "RFC 2822 date with positive offset");
}
# --- Date::Language error handling ---
{
eval { Date::Language->new('NonexistentLanguage') };
ok($@, "Date::Language->new with invalid language dies");
my $fr = Date::Language->new('French');
ok(defined $fr, "Date::Language->new('French') succeeds");
my $ts = $fr->str2time('15 janvier 2010');
ok(defined $ts, "French 'janvier' parses");
}
# --- French month parsing ---
{
my $fr = Date::Language->new('French');
my @months = (
['janvier', 1],
['mars', 3],
['juin', 6],
['octobre', 10],
['novembre', 11],
);
for my $pair (@months) {
my ($month_name, $month_num) = @$pair;
my $ts = $fr->str2time("15 $month_name 2010");
if (defined $ts) {
my @lt = localtime($ts);
is($lt[4] + 1, $month_num, "French '$month_name' -> month $month_num");
}
else {
fail("French '$month_name' failed to parse");
}
}
}
# --- Two-digit year handling ---
# Two-digit years: 69-99 -> 1969-1999, 0-68 -> 2000-2068 (POSIX convention)
{
my $t = str2time("16 Oct 09");
ok(defined $t, "two-digit year '09' parses");
cmp_ok($t, '>=', 0, "two-digit year '09' gives non-negative time");
my @gm = gmtime($t);
is($gm[5] + 1900, 2009, "two-digit year '09' maps to 2009");
}
# --- Two-digit years for 1970s/1980s dates (GH issue #47) ---
{
my $t74 = str2time("01 Jan 74 00:00:00 GMT");
ok(defined $t74, "two-digit year '74' parses");
is($t74, 126230400, "two-digit year '74' gives 1974-01-01 not 2074");
my $t73 = str2time("15 Jun 73 12:00:00 GMT");
ok(defined $t73, "two-digit year '73' parses");
my @gm73 = gmtime($t73);
is($gm73[5] + 1900, 1973, "two-digit year '73' maps to 1973");
my $t72 = str2time("01 Jan 72 00:00:00 GMT");
ok(defined $t72, "two-digit year '72' parses");
my @gm72 = gmtime($t72);
is($gm72[5] + 1900, 1972, "two-digit year '72' maps to 1972");
# Boundary: 69 -> 1969, 68 -> 2068
my $t69 = str2time("01 Jan 69 00:00:00 GMT");
ok(defined $t69, "two-digit year '69' parses");
my @gm69 = gmtime($t69);
is($gm69[5] + 1900, 1969, "two-digit year '69' maps to 1969 (boundary)");
}
# --- Time-only formats ---
{
my $t = str2time("10:00:00Z");
ok(defined $t, "time-only with Z parses");
my $t2 = str2time("10:00:00");
ok(defined $t2, "time-only without zone parses");
my $t3 = str2time("10:00");
ok(defined $t3, "time-only HH:MM parses");
}
# --- Various date separator styles ---
{
my $t1 = str2time("21 dec 17:05");
my $t2 = str2time("21-dec 17:05");
my $t3 = str2time("21/dec 17:05");
ok(defined $t1, "space-separated day month");
is($t1, $t2, "dash separator matches space separator");
is($t1, $t3, "slash separator matches space separator");
}
# --- Boost C++ timestamp format ---
{
my $t = str2time("2024-May-15 14:30:00.123456");
ok(defined $t, "boost format YYYY-Mon-DD HH:MM:SS.f parses");
}
# --- Leap day (Feb 29) handling ---
# When only a year is given, str2time fills in the current month/day.
# On Feb 29 the year must be a leap year or str2time returns undef.
# See: https://github.com/atoomic/perl-TimeDate/issues/28
{
# Explicit Feb 29 on a leap year must succeed
my $t1 = str2time("29 Feb 2000 10:02:18 GMT");
ok(defined $t1, "Feb 29 of leap year 2000 parses");
is($t1, 951818538, "Feb 29 2000 10:02:18 GMT matches expected epoch");
# Explicit Feb 29 on a non-leap year must fail
my $t2 = str2time("29 Feb 1999 10:02:18 GMT");
ok(!defined $t2, "Feb 29 of non-leap year 1999 returns undef");
}
# --- Comma as decimal separator in fractional seconds (ISO 8601) ---
{
my $dot = str2time("2016-01-28 23:27:13.995 UTC");
my $comma = str2time("2016-01-28 23:27:13,995 UTC");
ok(defined $dot, "dot decimal fractional seconds parse");
ok(defined $comma, "comma decimal fractional seconds parse");
cmp_ok(abs($dot - $comma), '<', 0.01,
"comma decimal gives same result as dot decimal");
my $t1 = str2time("2016-01-28 23:27:13,995 UTC");
my $t2 = str2time("2016-01-28 23:27:13,996 UTC");
cmp_ok($t2, '>', $t1,
"comma decimal: ,996 is later than ,995");
cmp_ok(abs($t2 - $t1 - 0.001), '<', 0.0001,
"comma decimal: difference is ~1ms");
# RFC 2822 commas still work
my $rfc = str2time("Wed, 16 Jun 94 07:29:35 CST");
is($rfc, 771773375, "RFC 2822 comma after day name still works");
}
# --- Year inference for dates without an explicit year (GH #46) ---
# When no year is given, str2time should assume the most recent occurrence:
# a date in the future (month > now, OR same month but day > today) gets
# previous year; a date in the past (or today) gets current year.
{
my @lt = localtime();
my ($cur_day, $cur_month, $cur_year) = @lt[3, 4, 5];
$cur_year += 1900;
my @mon_names = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
# A future month (strictly > current month): should infer previous year.
if ($cur_month < 11) {
my $future_mon = $mon_names[$cur_month + 1];
my $t = str2time("$future_mon 4 01:04:16");
ok(defined $t, "future month '$future_mon 4': parses");
my @res = localtime($t);
is($res[5] + 1900, $cur_year - 1,
"future month ($future_mon) → previous year (GH#46)");
}
# A past month (strictly < current month): should infer current year.
if ($cur_month > 0) {
my $past_mon = $mon_names[$cur_month - 1];
my $t = str2time("$past_mon 4 01:04:16");
ok(defined $t, "past month '$past_mon 4': parses");
my @res = localtime($t);
is($res[5] + 1900, $cur_year,
"past month ($past_mon) → current year (GH#46)");
}
# Same month, day strictly in the future → previous year.
if ($cur_day <= 27) {
my $future_day = $cur_day + 1;
my $mon = $mon_names[$cur_month];
my $t = str2time(sprintf("%s %d 01:04:16", $mon, $future_day));
ok(defined $t, "future day same month '$mon $future_day': parses");
my @res = localtime($t);
is($res[5] + 1900, $cur_year - 1,
"same month, future day ($mon $future_day) → previous year (GH#46)");
}
# Same month, day strictly in the past → current year.
if ($cur_day >= 2) {
my $past_day = $cur_day - 1;
my $mon = $mon_names[$cur_month];
my $t = str2time(sprintf("%s %d 01:04:16", $mon, $past_day));
ok(defined $t, "past day same month '$mon $past_day': parses");
my @res = localtime($t);
is($res[5] + 1900, $cur_year,
"same month, past day ($mon $past_day) → current year (GH#46)");
}
}
done_testing;
cpanrt-zone.t 100644 000765 000024 10041 15157412057 16047 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 15;
use Date::Parse qw(str2time);
use Time::Zone;
# IST (Indian Standard Time) should resolve to UTC+5:30
{
my $offset = tz_offset("ist");
is($offset, 19800, "tz_offset('ist') returns 19800 (UTC+5:30)");
my $time = str2time("2024-01-15 12:00:00 IST");
my $time_utc = str2time("2024-01-15 06:30:00 UTC");
is($time, $time_utc, "IST date parses to correct UTC equivalent");
}
# RT#76968: tz2zone("America/Chicago") doesn't work
# IANA timezone names like "America/Chicago" should be usable with tz_offset
{
use POSIX qw();
SKIP: {
# Verify that the system supports IANA timezone names
my $has_iana = eval {
local $ENV{TZ} = "Etc/UTC";
POSIX::tzset();
my ($std) = POSIX::tzname();
defined $std && $std =~ /UTC|GMT/i;
};
skip "system does not support IANA timezone names", 6 unless $has_iana;
# tz_offset with IANA name "Etc/UTC" must return 0 (deterministic)
my $utc_offset = tz_offset("Etc/UTC");
is($utc_offset, 0, "RT#76968: tz_offset('Etc/UTC') returns 0");
# tz2zone with IANA name "Etc/UTC" must return a valid abbreviation
my $utc_name = tz2zone("Etc/UTC", undef, 0);
ok(defined $utc_name && length($utc_name) > 0,
"RT#76968: tz2zone('Etc/UTC') returns a defined non-empty name");
# tz_offset(tz2zone(IANA_name)) must return defined — the key failure in the bug
my $chicago_abbr = tz2zone("America/New_York", undef, 0);
ok(defined $chicago_abbr,
"RT#76968: tz2zone('America/New_York', dst=0) returns defined");
my $chicago_offset = tz_offset($chicago_abbr);
ok(defined $chicago_offset,
"RT#76968: tz_offset(tz2zone('America/New_York')) returns defined");
# tz_offset of IANA name directly must return defined
my $ny_offset = tz_offset("America/New_York");
ok(defined $ny_offset,
"RT#76968: tz_offset('America/New_York') returns defined");
# tz_offset("Etc/UTC") via tz2zone round-trip
my $utc_abbr = tz2zone("Etc/UTC", undef, 0);
my $utc_offset2 = tz_offset($utc_abbr);
is($utc_offset2, 0,
"RT#76968: tz_offset(tz2zone('Etc/UTC')) returns 0");
}
}
# RT#59298: tz_name() reports incorrect offset for unknown timezone names
# The offset passed is in seconds, but the old code treated it as minutes,
# producing e.g. "+33000" for IST (+5:30) instead of "+0530".
# Also: negative fractional-hour offsets must format correctly.
{
# UTC+5:30 = 19800s — not in the Zone table when the bug was filed
is(tz_name(19800, 0), "ist", "RT#59298: tz_name(19800) returns ist (UTC+5:30 is now in table)");
# An offset not in the table: UTC+1:30 = 5400s → "+0130" (was "+9000" before fix)
is(tz_name(5400, 0), "+0130", "RT#59298: tz_name(5400) returns +0130, not +9000");
# Negative fractional offset: UTC-1:30 = -5400s → "-0130"
# (Note: -9000 is now NDT/Newfoundland Daylight, so use -5400 instead)
is(tz_name(-5400, 0), "-0130", "RT#59298: tz_name(-5400) returns -0130 (UTC-1:30)");
}
# RT#82271: tz_name should return CEST (not MEST) for Central European Summer Time
# CEST (Central European Summer Time) is the standard/preferred abbreviation;
# MEST (Middle European Summer Time) is a German-influenced variant.
{
is(tz_name(7200, 1), "cest", "RT#82271: tz_name(+2h, dst=1) returns cest not mest");
is(tz_offset("MEST"), 7200, "RT#82271: tz_offset(MEST) still works for backward compat");
}
# RT#98949: Moscow Time Change in October 2014
# MSK (Moscow Standard Time) is UTC+3 permanently since 25 Oct 2014.
# Russia eliminated DST in 2011 (UTC+4 year-round), then reverted to UTC+3 in Oct 2014.
{
my $offset = tz_offset("msk");
is($offset, 10800, "RT#98949: tz_offset('msk') returns 10800 (UTC+3)");
my $time = str2time("2014-10-27 00:00:00 MSK");
my $time_utc = str2time("2014-10-26 21:00:00 UTC");
is($time, $time_utc, "RT#98949: MSK date after 2014 change parses to correct UTC");
}
rt-timezone.t 100644 000765 000024 5433 15157412057 16055 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 10;
use Date::Parse qw(str2time);
use Time::Zone;
use POSIX qw();
# IST (Indian Standard Time) should resolve to UTC+5:30
{
my $offset = tz_offset("ist");
is($offset, 19800, "tz_offset('ist') returns 19800 (UTC+5:30)");
my $time = str2time("2024-01-15 12:00:00 IST");
my $time_utc = str2time("2024-01-15 06:30:00 UTC");
is($time, $time_utc, "IST date parses to correct UTC equivalent");
}
# RT#76968: tz2zone("America/Chicago") doesn't work
# IANA timezone names like "America/Chicago" should be usable with tz_offset
{
SKIP: {
# Verify that the system supports IANA timezone names
my $has_iana = eval {
local $ENV{TZ} = "Etc/UTC";
POSIX::tzset();
my ($std) = POSIX::tzname();
defined $std && $std =~ /UTC|GMT/i;
};
skip "system does not support IANA timezone names", 6 unless $has_iana;
# tz_offset with IANA name "Etc/UTC" must return 0 (deterministic)
my $utc_offset = tz_offset("Etc/UTC");
is($utc_offset, 0, "RT#76968: tz_offset('Etc/UTC') returns 0");
# tz2zone with IANA name "Etc/UTC" must return a valid abbreviation
my $utc_name = tz2zone("Etc/UTC", undef, 0);
ok(defined $utc_name && length($utc_name) > 0,
"RT#76968: tz2zone('Etc/UTC') returns a defined non-empty name");
# tz_offset(tz2zone(IANA_name)) must return defined — the key failure in the bug
my $chicago_abbr = tz2zone("America/New_York", undef, 0);
ok(defined $chicago_abbr,
"RT#76968: tz2zone('America/New_York', dst=0) returns defined");
my $chicago_offset = tz_offset($chicago_abbr);
ok(defined $chicago_offset,
"RT#76968: tz_offset(tz2zone('America/New_York')) returns defined");
# tz_offset of IANA name directly must return defined
my $ny_offset = tz_offset("America/New_York");
ok(defined $ny_offset,
"RT#76968: tz_offset('America/New_York') returns defined");
# tz_offset("Etc/UTC") via tz2zone round-trip
my $utc_abbr = tz2zone("Etc/UTC", undef, 0);
my $utc_offset2 = tz_offset($utc_abbr);
is($utc_offset2, 0,
"RT#76968: tz_offset(tz2zone('Etc/UTC')) returns 0");
}
}
# RT#98949: Moscow Time Change in October 2014
# MSK (Moscow Standard Time) is UTC+3 permanently since 25 Oct 2014.
# Russia eliminated DST in 2011 (UTC+4 year-round), then reverted to UTC+3 in Oct 2014.
{
my $offset = tz_offset("msk");
is($offset, 10800, "RT#98949: tz_offset('msk') returns 10800 (UTC+3)");
my $time = str2time("2014-10-27 00:00:00 MSK");
my $time_utc = str2time("2014-10-26 21:00:00 UTC");
is($time, $time_utc, "RT#98949: MSK date after 2014 change parses to correct UTC");
}
lib 000755 000765 000024 0 15157412057 13551 5 ustar 00nicolas staff 000000 000000 TimeDate-2.35 TimeDate.pm 100644 000765 000024 3276 15157412057 15753 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/lib package TimeDate;
our $VERSION = '2.35'; # VERSION: generated
# ABSTRACT: Date and time formatting subroutines
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
TimeDate - Date and time formatting subroutines
=head1 VERSION
version 2.35
=head1 SYNOPSIS
use Date::Format;
use Date::Parse;
# Formatting
print time2str("%Y-%m-%d %T", time); # 2024-01-15 14:30:00
print time2str("%a %b %e %T %Y\n", time); # Mon Jan 15 14:30:00 2024
# Parsing
my $time = str2time("Wed, 16 Jun 94 07:29:35 CST");
my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime("2024-01-15T14:30:00Z");
# Multi-language support
use Date::Language;
my $lang = Date::Language->new('German');
print $lang->time2str("%a %b %e %T %Y\n", time);
=head1 DESCRIPTION
The TimeDate distribution provides date parsing, formatting, and timezone
handling for Perl.
=over 4
=item L
Parse date strings in a wide variety of formats into Unix timestamps
or component values.
=item L
Format Unix timestamps or localtime arrays into strings using
C-style conversion specifications.
=item L
Format and parse dates in over 30 languages including French, German,
Spanish, Chinese, Russian, Arabic, and many more.
=item L
Timezone offset lookups and conversions for named timezones.
=back
=head1 SEE ALSO
L, L, L, L
=head1 AUTHOR
Graham
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2020 by Graham Barr.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
cpanrt-parse.t 100644 000765 000024 12112 15157412057 16207 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 26;
use Date::Parse qw(strptime str2time);
# RT#48164: Date::Parse unable to set seconds correctly
{
for my $str ("2008.11.30 22:35 CET", "2008-11-30 22:35 CET") {
my @t = strptime($str);
my $t = join ":", map { defined($_) ? $_ : "-" } @t;
is($t, "-:35:22:30:10:108:3600:20", "RT#48164: seconds parsing for '$str'");
}
}
# RT#51664: Change in str2time behaviour between 1.16 and 1.19
{
ok(str2time('16 Oct 09') >= 0, "RT#51664: '16 Oct 09' parses to non-negative time");
}
# RT#84075: Date::Parse::str2time maps date in 1963 to 2063
{
my $this_year = 1900 + (gmtime(time))[5];
my $target_year = $this_year - 50;
my $date = "$target_year-01-01 00:00:00 UTC";
my $time = str2time($date);
my $year_parsed_as = 1900 + (gmtime($time))[5];
is($year_parsed_as, $target_year, "RT#84075: year $target_year not mapped to future");
}
# RT#70650: Date::Parse should not parse ludicrous strings like bare numbers
{
ok(!defined str2time('1'), "RT#70650: str2time('1') returns undef");
ok(!defined str2time('+01'), "RT#70650: str2time('+01') returns undef");
ok(!defined str2time('+0500'), "RT#70650: str2time('+0500') returns undef");
}
# RT#53413 / RT#105031 (GH#17): Date::Parse mangling 4-digit year dates
# str2time() must not map 4-digit pre-1970 years to future dates.
# The root cause: strptime() extracts a 2-digit year (subtracting 1900 from
# the 4-digit value) and stores the century separately. str2time() must
# reconstruct the full 4-digit year before calling Time::Local, whose
# 2-digit-year windowing would otherwise map e.g. year 24 (from 1924) to 2024,
# or year 65 (from 1965) to 2065.
{
my @cases = (
[ "1924-01-15 00:00:00 UTC", 1924, "year 1924 does not map to 2024" ],
[ "1963-06-16 00:00:00 UTC", 1963, "year 1963 does not map to 2063" ],
[ "1965-12-31 00:00:00 UTC", 1965, "year 1965 does not map to 2065" ],
[ "1966-01-01 00:00:00 UTC", 1966, "year 1966 does not map to future" ],
[ "1901-12-17 00:00:00 UTC", 1901, "year 1901 parses correctly" ],
[ "1935-01-24 00:00:00 UTC", 1935, "year 1935 does not map to future" ],
);
for my $c (@cases) {
my ($date, $expected_year, $desc) = @$c;
my $t = str2time($date);
if (!defined $t) {
fail("RT#53413: str2time('$date') returned undef");
next;
}
my $parsed_year = 1900 + (gmtime($t))[5];
is($parsed_year, $expected_year, "RT#53413: $desc");
}
# strptime() must return year as offset from 1900 with century captured separately
my @t = strptime("1924-01-15 00:00:00 UTC");
is($t[5], 24, "RT#53413: strptime year field is 24 for 1924 (offset from 1900)");
is($t[7], 19, "RT#53413: strptime century field is 19 for 1924");
}
# RT#92611: str2time should pick the most recent occurrence when no year given.
# A future month means the most recent occurrence was last year.
{
my @lt = localtime(time);
my $cur_month = $lt[4]; # 0-11
my $cur_year = 1900 + $lt[5];
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
SKIP: {
# December → January crosses a year boundary; the heuristic is ambiguous there.
skip "RT#92611: skipping in December (year-boundary edge case)", 1
if $cur_month == 11;
my $future_month = $cur_month + 1; # guaranteed valid (0-10 → 1-11)
my $future_name = $months[$future_month];
my $t = str2time("15 $future_name");
my $got_year = 1900 + (localtime($t))[5];
is($got_year, $cur_year - 1,
"RT#92611: '15 $future_name' with no year resolves to previous year (most recent occurrence)");
}
}
# RT#53267 / GH#2: strptime('MONTH YEAR') puts year into $day
# 'December 2009' should give month=11, year=109 (2009-1900), day=undef
# not month=11, day=2009, year=undef
{
my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime('December 2009');
is($month, 11, "RT#53267: 'December 2009' gives month=11 (December)");
ok(!defined($day), "RT#53267: 'December 2009' gives day=undef (not 2009)");
is($year, 109, "RT#53267: 'December 2009' gives year=109 (2009-1900)");
# 4-digit year in same position
($ss,$mm,$hh,$day,$month,$year,$zone) = strptime('Jan 1995');
is($month, 0, "RT#53267: 'Jan 1995' gives month=0 (January)");
ok(!defined($day), "RT#53267: 'Jan 1995' gives day=undef");
is($year, 95, "RT#53267: 'Jan 1995' gives year=95 (1995-1900)");
# normal 'MONTH DAY' must still work
($ss,$mm,$hh,$day,$month,$year,$zone) = strptime('December 25');
is($month, 11, "RT#53267: 'December 25' still gives month=11");
is($day, 25, "RT#53267: 'December 25' still gives day=25");
}
# RT#125949: strptime returns negative month for certain inputs
{
my @t = strptime("199001");
my $month = $t[4];
ok(!defined($month) || $month >= 0,
"RT#125949: strptime('199001') month is not negative");
my $t = str2time("199001");
ok(!defined($t),
"RT#125949: str2time('199001') returns undef for ambiguous 6-digit input");
}
Time 000755 000765 000024 0 15157412057 14447 5 ustar 00nicolas staff 000000 000000 TimeDate-2.35/lib Zone.pm 100644 000765 000024 26316 15157412057 16110 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/lib/Time
package Time::Zone;
require 5.006;
require Exporter;
use Carp;
use strict;
use POSIX qw(tzset tzname);
our $VERSION = '2.35'; # VERSION: generated
# ABSTRACT: miscellaneous timezone manipulations routines
our @ISA = qw(Exporter);
our @EXPORT = qw(tz2zone tz_local_offset tz_offset tz_name);
# Parts stolen from code by Paul Foley
my %tzn_cache;
sub tz2zone (;$$$)
{
my($TZ, $time, $isdst) = @_;
$TZ = defined($ENV{'TZ'}) ? ( $ENV{'TZ'} ? $ENV{'TZ'} : 'GMT' ) : ''
unless $TZ;
# Hack to deal with 'PST8PDT' format of TZ
# Note that this can't deal with all the esoteric forms, but it
# does recognize the most common: [:]STDoff[DST[off][,rule]]
if (! defined $isdst) {
my $j;
$time = time() unless $time;
($j, $j, $j, $j, $j, $j, $j, $j, $isdst) = localtime($time);
}
if (defined $tzn_cache{$TZ}->[$isdst]) {
return $tzn_cache{$TZ}->[$isdst];
}
# Handle IANA timezone names (e.g., "America/Chicago", "Europe/Paris")
if ($TZ =~ m{/}) {
my ($std, $dst_name) = _iana_tzname($TZ);
$tzn_cache{$TZ} = [ $std, $dst_name ];
return $isdst ? $dst_name : $std;
}
if ($TZ =~ /^
( [^:\d+\-,] {3,} )
( [+-] ?
\d {1,2}
( : \d {1,2} ) {0,2}
)
( [^\d+\-,] {3,} )?
/x
) {
my $dsttz = defined($4) ? $4 : $1;
$TZ = $isdst ? $dsttz : $1;
$tzn_cache{$TZ} = [ $1, $dsttz ];
} else {
$tzn_cache{$TZ} = [ $TZ, $TZ ];
}
return $TZ;
}
my @tz_local;
sub tz_local_offset (;$)
{
my ($time) = @_;
$time = time() unless $time;
my (@l) = localtime($time);
my $isdst = $l[8];
if (defined($tz_local[$isdst])) {
return $tz_local[$isdst];
}
$tz_local[$isdst] = &calc_off($time);
return $tz_local[$isdst];
}
sub calc_off
{
my ($time) = @_;
my (@l) = localtime($time);
my (@g) = gmtime($time);
my $off;
$off = $l[0] - $g[0]
+ ($l[1] - $g[1]) * 60
+ ($l[2] - $g[2]) * 3600;
# subscript 7 is yday.
if ($l[7] == $g[7]) {
# done
} elsif ($l[7] == $g[7] + 1) {
$off += 86400;
} elsif ($l[7] == $g[7] - 1) {
$off -= 86400;
} elsif ($l[7] < $g[7]) {
# crossed over a year boundary!
# localtime is beginning of year, gmt is end
# therefore local is ahead
$off += 86400;
} else {
$off -= 86400;
}
return $off;
}
# Helper: temporarily set TZ to an IANA name, run a block, restore original TZ.
sub _with_iana_tz (&$) {
my ($code, $tz) = @_;
my $had_tz = exists $ENV{TZ};
my $saved = $ENV{TZ};
$ENV{TZ} = $tz;
tzset();
my @result = $code->();
if ($had_tz) { $ENV{TZ} = $saved } else { delete $ENV{TZ} }
tzset();
return @result;
}
# Return (std_name, dst_name) for an IANA timezone string.
sub _iana_tzname {
my ($tz) = @_;
my ($std, $dst) = _with_iana_tz { tzname() } $tz;
$dst = $std unless defined $dst;
return ($std, $dst);
}
# Return the UTC offset in seconds for an IANA timezone string at a given time.
sub _iana_offset {
my ($tz, $time) = @_;
$time = time() unless $time;
my ($off) = _with_iana_tz { calc_off($time) } $tz;
return $off;
}
# constants
my (%dstZone, %zoneOff, %dstZoneOff, %Zone);
CONFIG: {
my @dstZone = (
"ndt" => -2*3600-1800, # Newfoundland Daylight
"brst" => -2*3600, # Brazil Summer Time (East Daylight)
"adt" => -3*3600, # Atlantic Daylight
"edt" => -4*3600, # Eastern Daylight
"cdt" => -5*3600, # Central Daylight
"mdt" => -6*3600, # Mountain Daylight
"pdt" => -7*3600, # Pacific Daylight
"akdt" => -8*3600, # Alaska Daylight
"ydt" => -8*3600, # Yukon Daylight
"hdt" => -9*3600, # Hawaii Daylight
"bst" => +1*3600, # British Summer
"cest" => +2*3600, # Central European Summer (preferred)
"mest" => +2*3600, # Middle European Summer (alias, kept for compat)
"metdst" => +2*3600, # Middle European DST
"sst" => +2*3600, # Swedish Summer
"fst" => +2*3600, # French Summer
"eest" => +3*3600, # Eastern European Summer
"msd" => +4*3600, # Moscow Daylight (historical; Russia abolished DST permanently in Oct 2014)
"wadt" => +8*3600, # West Australian Daylight
"kdt" => +10*3600, # Korean Daylight
# "cadt" => +10*3600+1800, # Central Australian Daylight
"aedt" => +11*3600, # Eastern Australian Daylight
"eadt" => +11*3600, # Eastern Australian Daylight
"nzd" => +13*3600, # New Zealand Daylight
"nzdt" => +13*3600, # New Zealand Daylight
);
my @Zone = (
"gmt" => 0, # Greenwich Mean
"ut" => 0, # Universal (Coordinated)
"utc" => 0,
"wet" => 0, # Western European
"wat" => -1*3600, # West Africa
"at" => -2*3600, # Azores
"fnt" => -2*3600, # Brazil Time (Extreme East - Fernando Noronha)
"brt" => -3*3600, # Brazil Time (East Standard - Brasilia)
# For completeness. BST is also British Summer, and GST is also Guam Standard.
# "bst" => -3*3600, # Brazil Standard
# "gst" => -3*3600, # Greenland Standard
"nft" => -3*3600-1800,# Newfoundland
"nst" => -3*3600-1800,# Newfoundland Standard
"mnt" => -4*3600, # Brazil Time (West Standard - Manaus)
"ewt" => -4*3600, # U.S. Eastern War Time
"ast" => -4*3600, # Atlantic Standard
"est" => -5*3600, # Eastern Standard
"act" => -5*3600, # Brazil Time (Extreme West - Acre)
"cst" => -6*3600, # Central Standard
"mst" => -7*3600, # Mountain Standard
"pst" => -8*3600, # Pacific Standard
"akst" => -9*3600, # Alaska Standard
"yst" => -9*3600, # Yukon Standard
"hst" => -10*3600, # Hawaii Standard
"cat" => -10*3600, # Central Alaska
"ahst" => -10*3600, # Alaska-Hawaii Standard
"nt" => -11*3600, # Nome
"idlw" => -12*3600, # International Date Line West
"cet" => +1*3600, # Central European
"mez" => +1*3600, # Central European (German)
"ect" => +1*3600, # Central European (French)
"met" => +1*3600, # Middle European
"mewt" => +1*3600, # Middle European Winter
"swt" => +1*3600, # Swedish Winter
"set" => +1*3600, # Seychelles
"fwt" => +1*3600, # French Winter
"eet" => +2*3600, # Eastern Europe, USSR Zone 1
"ukr" => +2*3600, # Ukraine
"bt" => +3*3600, # Baghdad, USSR Zone 2
"msk" => +3*3600, # Moscow (UTC+3; was UTC+4 in 2011-2014 when Russia used permanent DST, reverted Oct 2014)
# "it" => +3*3600+1800,# Iran
"zp4" => +4*3600, # USSR Zone 3
"zp5" => +5*3600, # USSR Zone 4
"ist" => +5*3600+1800,# Indian Standard
"zp6" => +6*3600, # USSR Zone 5
# For completeness. NST is also Newfoundland Stanard, and SST is also Swedish Summer.
# "nst" => +6*3600+1800,# North Sumatra
# "sst" => +7*3600, # South Sumatra, USSR Zone 6
"ict" => +7*3600, # Indochina
# "jt" => +7*3600+1800,# Java (3pm in Cronusland!)
"ict" => +7*3600, # Indochina Time
"wst" => +8*3600, # West Australian Standard
"pht" => +8*3600, # Philippine
"hkt" => +8*3600, # Hong Kong
"pht" => +8*3600, # Philippine Time
"cct" => +8*3600, # China Coast, USSR Zone 7
"jst" => +9*3600, # Japan Standard, USSR Zone 8
"kst" => +9*3600, # Korean Standard
# "cast" => +9*3600+1800,# Central Australian Standard
"aest" => +10*3600, # Eastern Australian Standard
"east" => +10*3600, # Eastern Australian Standard
"gst" => +10*3600, # Guam Standard, USSR Zone 9
"nzt" => +12*3600, # New Zealand
"nzst" => +12*3600, # New Zealand Standard
"idle" => +12*3600, # International Date Line East
);
%Zone = @Zone;
%dstZone = @dstZone;
%zoneOff = reverse(@Zone);
%dstZoneOff = reverse(@dstZone);
}
sub tz_offset (;$$)
{
my ($zone, $time) = @_;
return &tz_local_offset($time) unless($zone);
$time = time() unless $time;
my(@l) = localtime($time);
my $dst = $l[8];
# Handle IANA timezone names (e.g., "America/Chicago") before lowercasing
if ($zone =~ m{/}) {
return _iana_offset($zone, $time);
}
$zone = lc $zone;
if($zone =~ /^(([\-\+])\d\d?)(\d\d)$/) {
my $v = $2 . $3;
return $1 * 3600 + $v * 60;
} elsif (exists $dstZone{$zone} && ($dst || !exists $Zone{$zone})) {
return $dstZone{$zone};
} elsif(exists $Zone{$zone}) {
return $Zone{$zone};
}
undef;
}
sub tz_name (;$$)
{
my ($off, $dst) = @_;
$off = tz_offset()
unless(defined $off);
$dst = (localtime(time))[8]
unless(defined $dst);
if (exists $dstZoneOff{$off} && ($dst || !exists $zoneOff{$off})) {
return $dstZoneOff{$off};
} elsif (exists $zoneOff{$off}) {
return $zoneOff{$off};
}
# $off is in seconds; format as +HHMM / -HHMM.
# Using abs() for the minutes component handles negative fractional-hour
# offsets correctly (e.g. -9000s = -2h30m → "-0230", not "-02-30").
sprintf("%+03d%02d", int($off / 3600), abs(int($off / 60)) % 60);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Time::Zone - miscellaneous timezone manipulations routines
=head1 VERSION
version 2.35
=head1 SYNOPSIS
use Time::Zone;
print tz2zone();
print tz2zone($ENV{'TZ'});
print tz2zone($ENV{'TZ'}, time());
my $isdst = 0;
print tz2zone($ENV{'TZ'}, undef, $isdst);
my $offset = tz_local_offset();
my $TZ = "EST";
$offset = tz_offset($TZ);
=head1 DESCRIPTION
This is a collection of miscellaneous timezone manipulation routines.
C parses the TZ environment variable and returns a timezone
string suitable for inclusion in L-like output. It optionally takes
a timezone string, a time, and a is-dst flag.
C determines the offset from GMT time in seconds. It
only does the calculation once.
C determines the offset from GMT in seconds of a specified
timezone.
C determines the name of the timezone based on its offset
=head1 NAME
Time::Zone -- miscellaneous timezone manipulations routines
=head1 AUTHORS
Graham Barr
David Muir Sharnoff
Paul Foley
=head1 AUTHOR
Graham
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2020 by Graham Barr.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
lang-encoding.t 100644 000765 000024 2307 15157412057 16302 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More;
use Date::Language;
# RT#113419 / GH#19: Language modules must return Unicode strings (UTF-8 flagged),
# not raw byte strings in legacy encodings.
#
# Legacy encoding modules (Chinese_GB, Russian, Russian_koi8r, Russian_cp1251)
# intentionally return byte strings and are excluded from this check.
my @unicode_langs = qw(
Afar
Amharic
Arabic
Austrian
Brazilian
Bulgarian
Chinese
Czech
Danish
Dutch
English
Finnish
French
Gedeo
German
Greek
Hungarian
Icelandic
Italian
Norwegian
Occitan
Oromo
Romanian
Sidama
Somali
Spanish
Swedish
Tigrinya
TigrinyaEritrean
TigrinyaEthiopian
Turkish
);
# Tue Sep 7 13:02:42 1999 GMT
my $time = 936709362;
for my $lang (@unicode_langs) {
my $l = Date::Language->new($lang);
for my $fmt (qw(%A %a %B %b)) {
my $str = $l->time2str($fmt, $time, 'GMT');
# Pure-ASCII strings don't get the UTF-8 flag; skip them.
next unless $str =~ /[^\x00-\x7f]/;
ok(
utf8::is_utf8($str),
"$lang $fmt: non-ASCII result has UTF-8 flag set"
);
}
}
done_testing;
time2str-lang.t 100644 000765 000024 1566 15157412057 16273 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 8;
use Date::Format qw(time2str);
# Unix timestamp for Tue Sep 7 11:22:42 1999 GMT (used in format.t)
my $t = 936709362;
# Baseline: English (default)
is( time2str('%A', $t, 'GMT'), 'Tuesday', 'English day (no lang arg)' );
is( time2str('%B', $t, 'GMT'), 'September', 'English month (no lang arg)');
# Explicit English via language argument
is( time2str('%A', $t, 'GMT', 'English'), 'Tuesday', 'English day (explicit)' );
is( time2str('%B', $t, 'GMT', 'English'), 'September', 'English month (explicit)');
# German
is( time2str('%A', $t, 'GMT', 'German'), 'Dienstag', 'German day' );
is( time2str('%B', $t, 'GMT', 'German'), 'September', 'German month');
# French
is( time2str('%A', $t, 'GMT', 'French'), 'mardi', 'French day' );
is( time2str('%B', $t, 'GMT', 'French'), 'septembre', 'French month');
cpanrt-format.t 100644 000765 000024 1127 15157412057 16351 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/t use strict;
use warnings;
use Test::More tests => 4;
use Date::Format qw(time2str strftime);
# RT#45067: Date::Format with %z gives wrong results for half-hour timezones
{
for my $zone (qw(-0430 -0445)) {
my $zone_str = time2str("%Z %z", time, $zone);
is($zone_str, "$zone $zone", "RT#45067: half-hour timezone $zone");
}
}
# RT#52387: seconds since the Epoch, UCT
{
my $time = time;
my @lt = localtime($time);
is(strftime("%s", @lt), $time, "RT#52387: strftime %s returns epoch");
is(time2str("%s", $time), $time, "RT#52387: time2str %s returns epoch");
}
Date 000755 000765 000024 0 15157412057 14426 5 ustar 00nicolas staff 000000 000000 TimeDate-2.35/lib Parse.pm 100644 000765 000024 31146 15157412057 16223 0 ustar 00nicolas staff 000000 000000 TimeDate-2.35/lib/Date # Copyright (c) 1995-2009 Graham Barr. This program is free
# software; you can redistribute it and/or modify it under the same terms
# as Perl itself.
package Date::Parse;
require 5.000;
use strict;
use Time::Local;
use Carp;
use Time::Zone;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(&strtotime &str2time &strptime);
our $VERSION = '2.35'; # VERSION: generated
# ABSTRACT: Parse date strings into time values
my %month = (
january => 0,
february => 1,
march => 2,
april => 3,
may => 4,
june => 5,
july => 6,
august => 7,
september => 8,
sept => 8,
october => 9,
november => 10,
december => 11,
);
my %day = (
sunday => 0,
monday => 1,
tuesday => 2,
tues => 2,
wednesday => 3,
wednes => 3,
thursday => 4,
thur => 4,
thurs => 4,
friday => 5,
saturday => 6,
);
my @suf = (qw(th st nd rd th th th th th th)) x 3;
@suf[11,12,13] = qw(th th th);
#Abbreviations
map { $month{substr($_,0,3)} = $month{$_} } keys %month;
map { $day{substr($_,0,3)} = $day{$_} } keys %day;
my $strptime = <<'ESQ';
my %month = map { lc $_ } %$mon_ref;
my $daypat = join("|", map { lc $_ } reverse sort keys %$day_ref);
my $monpat = join("|", reverse sort keys %month);
my $sufpat = join("|", reverse sort map { lc $_ } @$suf_ref);
my %ampm = (
'a' => 0, # AM
'p' => 12, # PM
);
my($AM, $PM) = (0,12);
sub {
my $dtstr = lc shift;
my $merid = 24;
my($century,$year,$month,$day,$hh,$mm,$ss,$zone,$dst,$frac);
$zone = tz_offset(shift) if @_;
1 while $dtstr =~ s#\([^\(\)]*\)# #o;
$dtstr =~ s#(\A|\n|\Z)# #sog;
# ignore day names
$dtstr =~ s#([\d\w\s])[\.\,]\s#$1 #sog;
$dtstr =~ s/(? 12;
return if length($year) > 2 and $year < 1901;
}
}
elsif ($dtstr =~ s#\s(\d+)\s*($sufpat)?\s*($monpat)# #o) {
($month,$day) = ($month{$3},$1);
}
elsif ($dtstr =~ s#($monpat)\s*(\d+)\s*($sufpat)?\s# #o) {
$month = $month{$1};
if ($2 > 31) { $year = $2 } else { $day = $2 }
}
elsif ($dtstr =~ s#($monpat)([\/-])(\d+)[\/-]# #o) {
($month,$day) = ($month{$1},$3);
}
# Date: 961212 (YYMMDD — only consume if month is in range 1-12)
elsif ($dtstr =~ /\s(\d\d)(\d\d)(\d\d)\s/o && $2 >= 1 && $2 <= 12) {
$dtstr =~ s/\s(\d\d)(\d\d)(\d\d)\s/ /;
($year,$month,$day) = ($1,$2-1,$3);
}
$year = $1 if !defined($year) and $dtstr =~ s#\s(\d{2}(\d{2})?)[\s\.,]# #o;
}
# Zone
$dst = 1 if $dtstr =~ s#\bdst\b##o;
if ($dtstr =~ s#\s"?([a-z]{3,4})(dst|\d+[a-z]*|_[a-z]+)?"?\s# #o) {
$dst = 1 if $2 and $2 eq 'dst';
$zone = tz_offset($1);
return unless defined $zone;
}
elsif ($dtstr =~ s#\s([a-z]{3,4})?([\-\+]?)-?(\d\d?):?(\d\d)?(00)?\s# #o) {
my $m = defined($4) ? "$2$4" : 0;
my $h = "$2$3";
$zone = defined($1) ? tz_offset($1) : 0;
return unless defined $zone;
$zone += 60 * ($m + (60 * $h));
}
if ($dtstr =~ /\S/) {
# now for some dumb dates
if ($dtstr =~ s/^\s*(ut?|z)\s*$//) {
$zone = 0;
}
elsif ($dtstr =~ s#\s([a-z]{3,4})?([\-\+]?)-?(\d\d?)(\d\d)?(00)?\s# #o) {
my $m = defined($4) ? "$2$4" : 0;
my $h = "$2$3";
$zone = defined($1) ? tz_offset($1) : 0;
return unless defined $zone;
$zone += 60 * ($m + (60 * $h));
}
return if $dtstr =~ /\S/o;
}
if (defined $hh) {
if ($hh == 12) {
$hh = 0 if $merid == $AM;
}
elsif ($merid == $PM) {
$hh += 12;
}
}
if (defined $year && $year >= 100) {
$century = int($year / 100);
$year -= 1900;
}
$zone += 3600 if defined $zone && $dst;
$ss += "0.$frac" if $frac;
# Reject inputs that produced only a timezone with no date/time components.
# A bare number like '1' or '+0500' gets consumed by the timezone regex,
# leaving no meaningful date or time information — these are not valid dates.
return unless defined $hh || defined $mm || defined $ss
|| defined $day || defined $month || defined $year;
return ($ss,$mm,$hh,$day,$month,$year,$zone,$century);
}
ESQ
our ($day_ref, $mon_ref, $suf_ref, $obj);
sub gen_parser
{
local($day_ref,$mon_ref,$suf_ref,$obj) = @_;
if($obj)
{
my $obj_strptime = $strptime;
substr($obj_strptime,index($strptime,"sub")+6,0) = <<'ESQ';
shift; # package
ESQ
my $sub = eval "$obj_strptime" or die $@;
return $sub;
}
eval "$strptime" or die $@;
}
*strptime = gen_parser(\%day,\%month,\@suf);
sub str2time
{
my $now = @_ > 2 ? splice(@_, 2, 1) : time;
my @t = strptime(@_);
return undef
unless @t;
my($ss,$mm,$hh,$day,$month,$year,$zone, $century) = @t;
my @lt = localtime($now);
$hh ||= 0;
$mm ||= 0;
$ss ||= 0;
my $frac = $ss - int($ss);
$ss = int $ss;
$month = $lt[4]
unless(defined $month);
$day = $lt[3]
unless(defined $day);
unless (defined $year) {
my $is_future = $month > $lt[4]
|| ($month == $lt[4] && $day > $lt[3]);
$year = $is_future ? ($lt[5] - 1) : $lt[5];
}
# we were given a 4 digit year, so let's keep using those
$year += 1900 if defined $century;
# Normalize two-digit years to 4-digit before passing to Time::Local.
# Time::Local's own windowing varies across versions, so we do it ourselves.
# Convention: 69-99 -> 1969-1999, 0-68 -> 2000-2068 (POSIX strptime behavior).
# Note: first-century dates (years 1-99 AD) are not representable through
# str2time — same limitation as POSIX strptime.
$year += ($year >= 69 ? 1900 : 2000) if $year < 100;
return undef
unless($month <= 11 && $day >= 1 && $day <= 31
&& $hh <= 23 && $mm <= 59 && $ss <= 59);
my $result;
if (defined $zone) {
$result = eval {
local $SIG{__DIE__} = sub {}; # Ick!
timegm($ss,$mm,$hh,$day,$month,$year);
};
return undef
if !defined $result
or $result == -1
&& join("",$ss,$mm,$hh,$day,$month,$year)
ne "595923311169";
# Detect integer overflow: post-1970 dates must produce a non-negative epoch
return undef if $result < 0 && $year >= 1970;
$result -= $zone;
}
else {
$result = eval {
local $SIG{__DIE__} = sub {}; # Ick!
timelocal($ss,$mm,$hh,$day,$month,$year);
};
return undef
if !defined $result
or $result == -1
&& join("",$ss,$mm,$hh,$day,$month,$year)
ne join("",(localtime(-1))[0..5]);
# Detect integer overflow: post-1970 dates must produce a non-negative epoch
# Use 1971 to avoid false positives from timezone offsets near epoch 0
return undef if $result < 0 && $year >= 1971;
}
return $result + $frac;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Date::Parse - Parse date strings into time values
=head1 VERSION
version 2.35
=head1 SYNOPSIS
use Date::Parse;
my $date = "Wed, 16 Jun 94 07:29:35 CST";
my $time = str2time($date);
my ($ss,$mm,$hh,$day,$month,$year,$zone) = strptime($date);
=head1 DESCRIPTION
C provides two routines for parsing date strings into time values.
=over 4
=item str2time(DATE [, ZONE [, EPOCH]])
C parses C and returns a unix time value, or undef upon failure.
C, if given, specifies the timezone to assume when parsing if the
date string does not specify a timezone.
C, if given, is a unix epoch value used as the reference time when
filling in missing date components (month, day, or year). Defaults to
C