File Coverage

blib/lib/Time/PT.pm
Criterion Covered Total %
statement 130 601 21.6
branch 49 300 16.3
condition 7 213 3.2
subroutine 14 57 24.5
pod 5 35 14.2
total 205 1206 17.0


line stmt bran cond sub pod time code
1             # 2CN4sip - Time::PT.pm (PipTime) created by Pip@CPAN.Org to define
2             # simple objects for storing instants in time.
3             # Desc: PT describes a simple object which encapsulates 10 fields:
4             # Century, Year, Month, Day, hour, minute, second, frame, jink, zone
5             # where frame is normally 1/60th-of-a-second && jink is normally
6             # 1/60th-of-a-frame. The objects describe a high-precision time-
7             # instant with fields in decending order of precision such that
8             # alphabetic listings will (typically) show time ascension && field
9             # arithmetic can be easily performed. PT objects can
10             # be added to / subtracted from Time::Frame objects to yield
11             # new specific PT instants.
12             # The common use of PT is for a simple `pt` utility to
13             # en/decode dates && times using seven (7) Base64 characters.
14             # 1st: '0A1B2C3'
15             # 2nd: 'Yd:2003,j:A7_,M:a3I' or 'f:3aL9.eP'
16             # if field name ends with d, value is read as decimal nstd of default b64.
17             # Third way is super verbose decimal strings:
18             # '15 years, 3 months, 7 weeks, 4 jinx' can use any (or none) sep but :
19             # 4th is hash
20             # Total Jinx possible for PT: 1,680,238,080,000,000 (1.7 quatrillion)
21             # JnxPTEpoch -> `pt __nWO0000` -> Midnight Jan. 1 7039 BCE
22             # PTEpoch -> `pt _nWO` -> Midnight Jan. 1 1361 CE
23             # PT members:
24             # new inits either with pt-param, expanded, or empty
25             #
26             # epoch_(seconds|frames|jinx)() methods (optional frames/jinx as floats)
27             # ptepoch_(seconds|frames|jinx)() methods
28             # (since ptEpoch (`pt _nWO` Midnight, Jan1,1361))
29             # settle fields with options (like return new Frame object with only
30             # total secs of old)
31             # re-def frame as other than 60th-of-a-second
32             # re-def jink as other than 60th-of-a-frame
33             # eg. def f && j limits as 31.6227766016838 (sqrt(1000)) for ms jinx
34             # or just def f as 1000 for exactly ms frames
35             # allow month/year modes to be set to avg or relative
36             #
37             # My Base64 encoding uses characters: 0-9 A-Z a-z . _ since I don't like
38             # having spaces or plusses in my time strings. I need times to be easy to
39             # append to filenames for very precise, consice, time-stamp versioning.
40             # Each encoded character represents (normally) just a single date or time
41             # field. All fields are 0-based except Month && Day. The fields are:
42             # Year-2000, Month, Day, Hour, Minute, Second, Frame (60th-of-a-second)
43             # There are three (3) exceptions to the rule that each character only
44             # represents one date or time field. The bits are there so... why not? =)
45             # 0) Each 12 added to the Month adds 64 to the Year.
46             # 1) 24 added to the Hour adds 320 to the Year.
47             # 2) 31 added to the Day makes the year negative just before adding
48             # 2000.
49             # So with all this, any valid pt (of 7 b64 characters) represents a unique
50             # instant (precise down to a Frame [60th-of-a-second]) that occurred or
51             # will occur between the years 1361 && 2639 (eg. New Year's Day of each
52             # of those years would be '_nWO' && '_n1O'). These rules break down as:
53             # Hour Day Month Year YearWith2000
54             # 24-47 32-62 49-60 -639- -576 1361-1424
55             # 37-48 -575- -512 1425-1488
56             # 25-36 -511- -448 1489-1552
57             # 13-24 -447- -384 1553-1616
58             # 1-12 -383- -320 1617-1680
59             # 0-23 32-62 49-60 -319- -256 1681-1744
60             # 37-48 -255- -192 1745-1808
61             # 25-36 -191- -128 1809-1872
62             # 13-24 -127- -64 1873-1936
63             # 1-12 -63- -0 1937-2000
64             # 0-23 1-31 1-12 0- 63 2000-2063
65             # 13-24 64- 127 2064-2127
66             # 25-36 128- 191 2128-2191
67             # 37-48 192- 255 2192-2255
68             # 49-60 256- 319 2256-2319
69             # 24-47 1-31 1-12 320- 383 2320-2383
70             # 13-24 384- 447 2384-2447
71             # 25-36 448- 511 2448-2511
72             # 37-48 512- 575 2512-2575
73             # 49-60 576- 639 2576-2639
74             # Notz:
75             # PT + Frame can become the core of a new input language which accounts
76             # for time. It could be game sequences like a fireball that can be rolled
77             # from d->df && df->f only at a certain speed ... but then also later
78             # maybe time-sensitive computer input like typematic key repeat rate but
79             # configurable... smarter? The combinatorics on the X-Box Live pswd is
80             # 8**4 == 4096 (butn: u,d,l,r,x,y,L,R) so even exhausting the search space
81             # (assuming you're too wise for a smpl likely 4-char sequence) could be
82             # finished manually in about 9 hours if you complete a test cycle each
83             # 8 seconds. Automated would need programmable circuit... plug that
84             # thang into USB && make an easy sequencer PT+Frame- based IF to perform!
85             # So cool!
86             # Could create an easy IF to setup any sort of practice scenario,
87             # programmable pad behavior, or even store replays as device inputs &&
88             # feed them back in... woohoo that's fscking cool! GameOver specialty =)
89             # umm it would basically need the same IF as a fighting game tool hehe =).
90             # Don't need Math::BigInt to store pt epoch seconds (pte's) because perl's
91             # floats already have enough precision to store them. Use the fractional
92             # part of those values to store 60ths && don't use builtin timelocal
93             # functions which only accept 1970-2036 (or whatever limited) epoch
94             # seconds (only 32-bit ints or something =( ).
95             # Interaction with other Time modules:
96             # Time::Period - just have an Epoch export option && Period can use it
97             # Time::Avail - doesn't seem useful to my purposes
98             # Time::Piece - might be nice to mimic this module's object interface
99             # Time::Seconds - handy for dealing with lots of seconds but about 60ths?
100             # old 5-char pt examples: (update these when there's time)
101             # Xmpl: `pt 01` == localtime(975657600) # seconds since Epoch
102             # `pt 1L7Mu` == unpack time (Sun Jan 21 07:22:56 2001)
103             # `pt _VNxx` == localtime(1143878399)
104             # `pt pt` == unpack current pt (akin to `pt `pt``)
105             # `pt e` == localtime (eg. Thu Jan 21 07:22:56 2001)
106             # `pt e e` == current epoch seconds
107             # `pt 1L7Mu e` == convert from pt to epoch (980090576)
108             # `pt 975657600 E` == convert from Epoch seconds to pt (01)
109             # `pt Jan 21, 2001 07:22:56` -> 1L7Mu
110             # `pt Sun Jan 21 07:22:56 2001` -> 1L7Mu
111             # `pt 1L7Mu cmp FEET0` -> lt
112             # `pt FEET0 cmp 1L7Mu` -> gt
113             # `pt 2B cmp 2B` -> eq
114             # timelocal($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
115              
116             =head1 NAME
117              
118             Time::PT - objects to store an instant in time
119              
120             =head1 VERSION
121              
122             This documentation refers to version 1.2.565EHOV of
123             Time::PT, which was released on Sun Jun 5 14:17:24:31 2005.
124              
125             =head1 SYNOPSIS
126              
127             use Time::PT;
128            
129             my $f = Time::PT->new();
130            
131             print "PipTime is: $f\n";
132             print 'The Day-of-Week today is: ', $f->dow(), "\n";
133              
134             =head1 DESCRIPTION
135              
136             By default, Time::PT stores time descriptions precise to 60ths-
137             of-a-second (0.016667 seconds). The groundwork has been laid
138             for sub-millisecond precision to be included later.
139              
140             This module has been adapted from the L module
141             written by Matt Sergeant && Jarkko
142             Hietaniemi . Time::PT inherits base
143             data structure && object methods from L.
144             PT was written to simplify storage && calculation
145             of encoded, yet distinct && human-readable, time data
146             objects.
147              
148             This module (Time::PT) does not replace the standard localtime &&
149             gmtime functions like L but Time::PT objects behave
150             almost identically to L objects otherwise (since it
151             was adapted from... I said that already =) ).
152              
153             =head1 2DO
154              
155             =over 2
156              
157             =item - mk interoperable w/ Time::Seconds objects
158              
159             =item - add Time::Zone stuff to use && match zone field reasonably
160              
161             =item - replace legacy pt() with tested new() wrapper && fix all apps to
162             use objs instead of local pt()
163              
164             =item - flesh out constructor init data parsing && formats supported
165              
166             =item - consider epoch functions like _epoch([which epoch]) or individuals
167             like _jinx_epoch()
168              
169             =item - mk PT->new able to create from different 'epoch' init types
170              
171             =item - fix weird 0 month && 0 day problems
172              
173             =item - What else does PT need?
174              
175             =back
176              
177             =head1 WHY?
178              
179             The reason I created PT was that I have grown so enamored with
180             Base64 representations of everything around me that I was
181             compelled to write a simple clock utility ( `pt` ) using Base64.
182             This demonstrated the benefit to be gained from time objects with
183             distinct fields && configurable precision. Thus, L
184             was written to be the abstract base class for:
185              
186             Time::Frame ( creates objects which represent spans of time )
187             &&
188             Time::PT ( creates objects which represent instants in time )
189              
190             =head2 HOW?
191              
192             I've made up some silly sentences as mnemonic devices to help me
193             remember every 4th uppercase Base64 character:
194              
195             Can 12 Noon MonthOfYear will be less or equal to 'C'.
196             Goats 16 4 PM
197             Keep 20 8 PM
198             Oats 24 Midnight HourOfDay will be less than 'O'.
199             Some 28
200             Where? 32 DayOfMonth will be less than 'W'.
201              
202             Cool COW (Month Hour Day thresholds)
203             Guys Girls
204             Keep Keep
205             On On Off
206             Sayin' Sayin' Sippin' Sea
207             Wassup WeeDoggies Water Water
208              
209             =head1 USAGE
210              
211             Many of Time::PT's methods have been patterned after the excellent
212             L module written by Matt Sergeant
213             && Jarkko Hietaniemi .
214              
215             =head2 new(, )
216              
217             Time::PT's constructor can be called
218             as a class method to create a brand new object or as an object
219             method to copy an existing object. Beyond that, new() can
220             initialize PT objects 3 different ways:
221              
222             *
223             eg. Time::PT->new('3C79jo0');
224             * 'str' =>
225             eg. Time::PT->new('str' => '0A1B2C3D4E');
226             * 'list' =>
227             eg. Time::PT->new('list' => [0, 1, 2..9]);
228             * 'hash' =>
229             eg. Time::PT->new('hash' => {'jink' => 8, 'year' => 2003})
230              
231             =head2 color()
232              
233             This is an object member
234             which will join Base64 representations of each field that has
235             been specified in use() && joins them with color-codes or color
236             escape sequences with formats for varied uses. Currently
237             available DestinationColorTypeFormats are:
238              
239             'ANSI' # eg. \e[1;32m
240             'zsh' # eg. %{\e[1;33m%}
241             'HTML' # eg.
242             '4NT' # eg. color 09 &
243             'Simp' # eg. RbobYbGbCbUbPb
244              
245             =head2 pt
246              
247             This function is the legacy procedural version of my command-line
248             PipTime utility. It will be removed in the near future when the
249             object methods fully replace all the old behavior && have been
250             tested sufficiently.
251              
252             This function && the following ptcc() are the only functions
253             exported when Time::PT is used.
254              
255             =head2 ptcc()
256              
257             Returns the Simp color code string appropriate for pt (PipTime) data.
258              
259             Format Returned color code string
260             'k' the background will change along with the foreground for standard
261             time-of day elements (ie. hms on a dark blue background)
262             'f' color codes for the expanded pt format
263             (eg. color codes corresponding to Sun Jan 4 12:41:48:13 2004)
264              
265             This function && the previous legacy pt() are the only functions
266             exported when Time::PT is used.
267              
268             The following methods allow access to individual fields of
269             Time::PT objects:
270              
271             $t->C or $t->century
272             $t->Y or $t->year
273             $t->M or $t->month
274             $t->D or $t->day
275             $t->h or $t->hour
276             $t->m or $t->minute
277             $t->s or $t->second
278             $t->f or $t->frame
279             $t->j or $t->jink
280             $t->z or $t->zone
281              
282             Please see L for further description of field
283             accessor methods.
284              
285             After importing this module, when you use localtime or gmtime in a
286             scalar context, you DO NOT get a special Time::PT object like you
287             would when using L. This module relies on a new()
288             constructor instead. The following methods are available on
289             Time::PT objects though && remain as similar to L
290             functionality as makes sense.
291              
292             $t->frm # also as $t->frame && $t->subsecond
293             $t->sec # also available as $t->second
294             $t->min # also available as $t->minute
295             $t->hour # 24 hour
296             $t->mday # also available as $t->day_of_month
297             $t->mon # 1 = January
298             $t->_mon # 0 = January
299             $t->monname # Feb
300             $t->month # same as $t->mon
301             # *NOTE* The above definition ( of $t->month() ) is
302             # different from the Time::Piece interface which defines
303             # month() the same as monname() instead of mon().
304             $t->fullmonth # February
305             $t->year # based at 0 (year 0 AD is, of course 1 BC)
306             $t->_year # year minus 1900
307             $t->yy # 2 digit year
308             $t->wday # 1 = Sunday
309             $t->_wday # 0 = Sunday
310             $t->day_of_week # 0 = Sunday
311             $t->wdayname # Tue
312             $t->day # same as mday
313             # *NOTE* Similar to month(), I've defined day()
314             # differently from Time::Piece which makes it the same
315             # as wdayname() instead of mday().
316             $t->fullday # Tuesday
317             $t->yday # also available as $t->day_of_year, 0 = Jan 01
318             $t->isdst # also available as $t->daylight_savings
319              
320             The following functions return a list of the named fields. The
321             return value can be joined with any desirable delimiter like:
322              
323             join(':', $t->hms);
324             join($t->time_separator, $t->hms);
325              
326             but the functions also can take a list of parameters to update
327             the corresponding named fields like:
328              
329             $t->YMD( 2003, 12, 8 ) # assigns new date of December 8th, 2003 to $t
330              
331             Following are some useful functions && comments of sample return values:
332              
333             $t->hms # [12, 34, 56]
334             $t->hmsf # [12, 34, 56, 12]
335             $t->time # same as $t->hmsf
336              
337             $t->ymd # [2000, 2, 29]
338             $t->date # same as $t->ymd
339             $t->mdy # [ 2, 29, 2000]
340             $t->dmy # [29, 2, 2000]
341             $t->datetime # 2000-02-29T12:34:56 (ISO 8601)
342             $t->expand # Tue Feb 29 12:34:56:12 2000
343             $t->cdate # same as $t->expand
344             $t->compress # 02TCYuC
345             "$t" # same as $t->compress
346              
347             $t->is_leap_year # true if it is
348             $t->month_last_day # 28-31
349              
350             $t->time_separator($s) # set the default separator (default ":")
351             $t->date_separator($s) # set the default separator (default "-")
352             $t->day_list(@days) # set the default weekdays
353             $t->mon_list(@days) # set the default months
354              
355             =head2 Local Locales
356              
357             Both wdayname() && monname() can accept the same list parameter
358             as day_list() && mon_list() respectively for temporary help with
359             simple localization.
360              
361             my @days = ( 'Yom Rishone', 'Yom Shayni', 'Yom Shlishi', 'Yom Revi\'i',
362             'Yom Khahmishi', 'Yom Hashishi', 'Shabbat' );
363              
364             my $hebrew_day = pt->wdayname(@days);
365             # pt->monname() can be used similarly
366              
367             To update the global lists, use:
368              
369             Time::PT::day_list(@days);
370             &&
371             Time::PT::mon_list(@months);
372              
373             =head2 Calculations
374              
375             PT object strings (both in normal initialization && printing) grow
376             left-to-right starting from the Year to specify whatever precision
377             you need while Frame objects grow right-to-left from the frame field.
378              
379             It's possible to use simple addition and subtraction of objects:
380              
381             use Time::Frame;
382            
383             my $cur_pt = Time::PT->new();# Dhmsf
384             my $one_week = Time::Frame->new('70000');
385             my $one_week_ago = $cur_pt - $one_week;
386              
387             If a calculation is done with a raw string parameter instead of an
388             instantiated object, the most likely appropriate object
389             constructor is called on it. These init strings must adhere to
390             the implied 'str' format for auto-creating objects; I aim to
391             support a much wider array of operations && to make this module
392             smoothly interoperate with both L && L
393             someday but not yet.
394              
395             my $cur_pt = Time::PT->new();
396             my $half_hour_from_now = $cur_pt + 'U00';
397              
398             The following are valid (where $t0 and $t1 are Time::PT objects
399             && $f is a Time::Frame object):
400              
401             $t0 - $t1; # returns Time::Frame object
402             $t0 - '63'; # returns Time::PT object
403             $t0 + $f; # returns Time::PT object
404              
405             =head2 Comparisons
406              
407             All normal numerical && string comparisons should work reasonably on
408             Time::PT objects:
409              
410             "<", ">", "<=", ">=", "<=>", "==" && "!="
411             "lt", "gt", "le", "ge", "cmp", "eq" and "ne"
412              
413             =head2 YYYY-MM-DDThh:mm:ss
414              
415             The ISO 8601 standard defines the date format to be YYYY-MM-DD, and
416             the time format to be hh:mm:ss (24 hour clock), and if combined,
417             they should be concatenated with date first and with a capital 'T'
418             in front of the time.
419              
420             =head2 Week Number
421              
422             The ISO 8601 standard specifies that weeks begin on Monday and the first
423             week of the year is the one that includes both January 4th and the
424             first Thursday of the year. In other words, if the first Monday of
425             January is the 2nd, 3rd, or 4th, the preceding days are part of the
426             final week of the prior year. Week numbers range from 1 to 53.
427              
428             =head1 NOTES
429              
430             Whenever individual Time::PT attributes are going to be
431             printed or an entire object can be printed with multi-colors,
432             the following mapping should be employed whenever possible:
433              
434             D Century -> DarkRed
435             A Year -> Red
436             T Month -> Orange
437             E Day -> Yellow
438             hour -> Green
439             t minute -> Cyan
440             i second -> Blue
441             m frame -> Purple
442             e jink -> DarkPurple
443             zone -> Grey or White
444              
445             Please see the color() member function in the USAGE section.
446              
447             There's some weird behavior for PipTimes created with a zero month
448             or day field since both are 1-based. I aim to fix all these bugs
449             but be warned that this issue may be causing math errors for a bit.
450              
451             I hope you find Time::PT useful. Please feel free to e-mail
452             me any suggestions || coding tips || notes of appreciation
453             ("app-ree-see-ay-shun"). Thank you. TTFN.
454              
455             =head1 CHANGES
456              
457             Revision history for Perl extension Time::PT:
458              
459             =over 4
460              
461             =item - 1.2.565EHOV Sun Jun 5 14:17:24:31 2005
462              
463             * updated test.pl to work properly with Build.PL as well as Makefile.PL
464              
465             * updated License, minor version, && precision description
466              
467             =item - 1.0.42M3ChX Sun Feb 22 03:12:43:33 2004
468              
469             * added 4NT option to color codes in Fields && color() members in Frame && PT
470              
471             * updated POD links && CHANGES chronology
472              
473             =item - 1.0.41M4cZH Thu Jan 22 04:38:35:17 2004
474              
475             * moved pt, fpt, && lspt into bin/ for packaging as EXE_FILES
476              
477             * added Time::Frame::total_frames method
478              
479             =item - 1.0.418BGcv Thu Jan 8 11:16:38:57 2004
480              
481             * moved Curses::Simp::ptCC into Time::PT::ptcc for PipTime-specific Simp
482             Color Codes
483              
484             * created Time::Fields::_field_colors (centralized base class color codes)
485             && updated Frame && PT _color_fields
486              
487             * added HOW? POD section for mnemonics
488              
489             =item - 1.0.3CVL3V4 Wed Dec 31 21:03:31:04 2003
490              
491             * changed PREREQ to not have lib files from this pkg
492              
493             =item - 1.0.3CQ8ibf Fri Dec 26 08:44:37:41 2003
494              
495             * fixed typo && hardcoded path in VERSION_FROM of gen'd Makefile.PL
496              
497             =item - 1.0.3CNNQHc Tue Dec 23 23:26:17:38 2003
498              
499             * combined Fields, Frame, && PT into one pkg
500              
501             =item - 1.0.3CCA2VC Fri Dec 12 10:02:31:12 2003
502              
503             * removed indenting from POD NAME section
504              
505             =item - 1.0.3CBIQv7 Thu Dec 11 18:26:57:07 2003
506              
507             * updated test.pl to use normal comments
508              
509             =item - 1.0.3CB7Vxh Thu Dec 11 07:31:59:43 2003
510              
511             * added HTML color option && prepared for release
512              
513             =item - 1.0.3CA8ipi Wed Dec 10 08:44:51:44 2003
514              
515             * built class to inherit from Time::Fields && mimic Time::Piece
516              
517             =item - 1.0.37VG26k Thu Jul 31 16:02:06:46 2003
518              
519             * original version
520              
521             =back
522              
523             =head1 INSTALL
524              
525             Please run:
526              
527             `perl -MCPAN -e "install Time::PT"`
528              
529             or uncompress the package && run the standard:
530              
531             `perl Makefile.PL; make; make test; make install`
532              
533             =head1 FILES
534              
535             Time::PT requires:
536              
537             L to allow errors to croak() from calling sub
538              
539             L to handle simple number-base conversion
540              
541             L also stores global day && month names
542              
543             L
544              
545             L to provide underlying object structure
546              
547             L to represent spans of time
548              
549             Time::PT uses (if available):
550              
551             L to provide subsecond time precision
552              
553             L to turn epoch seconds back into a real date
554              
555             L not utilized yet
556              
557             =head1 SEE ALSO
558              
559             L
560              
561             =head1 LICENSE
562              
563             Most source code should be Free!
564             Code I have lawful authority over is && shall be!
565             Copyright: (c) 2002-2005, Pip Stuart.
566             Copyleft : This software is licensed under the GNU General Public
567             License (version 2). Please consult the Free Software Foundation
568             (http://FSF.Org) for important information about your freedom.
569              
570             =head1 AUTHOR
571              
572             Pip Stuart
573              
574             =cut
575              
576             package Time::PT;
577 1     1   7935 use strict;
  1         2  
  1         46  
578             require Time::Fields;
579             require Exporter;
580 1     1   6 use base qw( Time::Fields Exporter );
  1         2  
  1         586  
581 1     1   5 use vars qw( $AUTOLOAD );
  1         2  
  1         45  
582 1     1   4 use Carp;
  1         2  
  1         53  
583 1     1   7 use Math::BaseCnv qw( :all );
  1         1  
  1         158  
584 1     1   775 use Time::DayOfWeek;
  1         829  
  1         47  
585 1     1   719 use Time::DaysInMonth;
  1         361  
  1         48  
586 1     1   699 use Time::Frame;
  1         2  
  1         150  
587 1     1   7 my $hirs = eval("use Time::HiRes; 1") || 0;
  1         2  
  1         11  
588 1     1   7 my $locl = eval("use Time::Local; 1") || 0;
  1         1  
  1         56  
589 1     1   1003 my $zown = eval("use Time::Zone; 1") || 0;
  1         1958  
  1         72  
590             #my $simp = eval("use Curses::Simp; 1") || 0;
591             our $VERSION = '1.2.565EHOV'; # major . minor . PipTimeStamp
592             our $PTVR = $VERSION; $PTVR =~ s/^\d+\.\d+\.//; # strip major && minor
593             # Please see `perldoc Time::PT` for an explanation of $PTVR.
594             our @EXPORT = qw(pt ptcc);
595             use overload
596 1         9 q("") => \&_stringify,
597             q(<=>) => \&_cmp_num,
598             q(cmp) => \&_cmp_str,
599             q(+) => \&_add,
600 1     1   6 q(-) => \&_sub;
  1         1  
601              
602             sub _stringify { # cat non-zero b64 PT fields
603 12     12   597 my @fdat = $_[0]->CYMDhmsfjz();
604 12         55 my @attz = $_[0]->_attribute_names();
605 12         32 my $tstr = ''; my $toob = 0; # flag designating field too big
  12         28  
606 12         20 $fdat[1] -= 2000; # Year adjustment
607 12         30 foreach(@fdat) {
608 120 50       246 $toob = 1 if($_ > 63);
609             }
610             # Reverse Year shifts back into fields
611             # 0) Each 12 added to the Month adds 64 to the Year.
612             # 1) 24 added to the Hour adds 320 to the Year.
613             # 2) 31 added to the Day makes the year negative just before adding 2k
614 12 100       39 if( $fdat[1] < 0) { $fdat[1] *= -1; $fdat[3] += 31; }
  8         17  
  8         14  
615 12 100       36 if( $fdat[1] >= 320) { $fdat[1] -= 320; $fdat[4] += 24; }
  8         14  
  8         13  
616 12         32 while($fdat[1] >= 64) { $fdat[1] -= 64; $fdat[2] += 12; }
  208         190  
  208         384  
617 12 50       73 if($toob) {
618 0         0 for(my $i=0; $i<@fdat; $i++) {
619 0         0 $attz[$i] =~ s/^_(.).*/$1/;
620 0 0 0     0 $attz[$i] = uc($attz[$i]) if($i < 4 || $i == $#fdat);
621 0         0 $tstr .= $attz[$i] . ':' . $fdat[$i];
622 0 0       0 $tstr .= ', ' if($i < $#fdat);
623             }
624             } else {
625 12         40 for(my $i=0; $i<@fdat; $i++) {
626 46 100       4400 if($fdat[$i]) {
627 24         82 $tstr .= b64($fdat[$i]);
628 24         13647 while($i < 7) { $tstr .= b64($fdat[++$i]); }
  74         29777  
629             }
630             }
631             }
632 12         94 return($tstr);
633             }
634              
635             sub _cmp_num {
636 0     0   0 my ($larg, $rarg, $srvr) = @_;
637 0 0       0 ($larg, $rarg) = ($rarg, Time::PT->new($larg)) if($srvr); # mk both args PT objects
638 0 0 0     0 $rarg = Time::PT->new($rarg) unless(ref($rarg) && $rarg->isa('Time::PT'));
639 0 0 0     0 if (($larg->C < $rarg->C) ||
    0 0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
      0        
640             ($larg->Y < $rarg->Y) ||
641             ($larg->O < $rarg->O) ||
642             ($larg->D < $rarg->D) ||
643             ($larg->h < $rarg->h) || # add z?
644             ($larg->i < $rarg->i) ||
645             ($larg->s < $rarg->s) ||
646             ($larg->f < $rarg->f) ||
647 0         0 ($larg->j < $rarg->j)) { return(-1); }
648             elsif(($larg->C > $rarg->C) ||
649             ($larg->Y > $rarg->Y) ||
650             ($larg->O > $rarg->O) ||
651             ($larg->D > $rarg->D) ||
652             ($larg->h > $rarg->h) || # add z?
653             ($larg->i > $rarg->i) ||
654             ($larg->s > $rarg->s) ||
655             ($larg->f > $rarg->f) ||
656 0         0 ($larg->j > $rarg->j)) { return(1); }
657 0         0 else { return(0); }
658             }
659              
660             sub _cmp_str {
661 0     0   0 my $c = _cmp_num(@_);
662 0 0       0 ($c < 0) ? return('lt') : ($c) ? return('gt') : return('eq');
    0          
663             }
664              
665             # PT + Frame = PT
666             # PT + anything else is not supported yet
667             sub _add {
668 0     0   0 my ($larg, $rarg, $srvr) = @_;
669 0         0 my $rslt = Time::PT->new('');
670 0 0       0 if($srvr) {
671 0         0 ($larg, $rarg) = ($rarg, Time::Frame->new($larg));
672             }
673 0 0 0     0 unless(ref($rarg) && $rarg->isa('Time::Frame')) {
674 0         0 $rarg = Time::Frame->new($rarg);
675             }
676 0         0 $rslt->{'_zone'} = $larg->z + $rarg->z;
677 0         0 $rslt->{'_jink'} = $larg->j + $rarg->j;
678 0         0 $rslt->{'_frame'} = $larg->f + $rarg->f;
679 0         0 $rslt->{'_second'} = $larg->s + $rarg->s;
680 0         0 $rslt->{'_minute'} = $larg->i + $rarg->i;
681 0         0 $rslt->{'_hour'} = $larg->h + $rarg->h;
682 0         0 $rslt->{'_day'} = $larg->D + $rarg->D;
683 0         0 $rslt->{'_month'} = $larg->O;
684 0         0 $rslt->{'_year'} = $larg->Y;
685 0         0 $rslt->_sift();
686 0         0 $rslt->{'_month'} = $larg->O + $rarg->O;
687 0         0 $rslt->{'_year'} = $larg->Y + $rarg->Y;
688 0         0 $rslt->{'_century'} = $larg->C + $rarg->C;
689 0         0 $rslt->_sift(1);
690 0         0 return($rslt);
691             }
692              
693             # PT - Frame = PT
694             # PT - PT = Frame
695             # PT - anything else is not supported yet
696             sub _sub {
697 0     0   0 my ($larg, $rarg, $srvr) = @_; my $rslt;
  0         0  
698 0 0       0 if($srvr) {
699 0         0 $larg = Time::PT->new($larg);
700             }
701 0 0 0     0 if(ref($rarg) && $rarg->isa('Time::PT')) {
702 0         0 $rslt = Time::Frame->new();
703             } else {
704 0 0 0     0 $rarg = Time::Frame->new($rarg) unless(ref($rarg) && $rarg->isa('Time::Frame'));
705 0         0 $rslt = Time::PT->new('');
706             }
707 0         0 $rslt->{'_zone'} = $larg->z - $rarg->z;
708 0         0 $rslt->{'_jink'} = $larg->j - $rarg->j;
709 0         0 $rslt->{'_frame'} = $larg->f - $rarg->f;
710 0         0 $rslt->{'_second'} = $larg->s - $rarg->s;
711 0         0 $rslt->{'_minute'} = $larg->i - $rarg->i;
712 0         0 $rslt->{'_hour'} = $larg->h - $rarg->h;
713 0         0 $rslt->{'_day'} = $larg->D - $rarg->D;
714 0         0 $rslt->{'_month'} = $larg->O;
715 0         0 $rslt->{'_year'} = $larg->Y;
716 0 0       0 $rslt->_sift() if($rslt->isa('Time::PT'));
717 0         0 $rslt->{'_month'} = $larg->O - $rarg->O;
718 0         0 $rslt->{'_year'} = $larg->Y - $rarg->Y;
719 0         0 $rslt->{'_century'} = $larg->C - $rarg->C;
720 0 0       0 $rslt->_sift(1) if($rslt->isa('Time::PT'));
721 0         0 return($rslt);
722             }
723              
724             sub _sift { # settles fields into standard ranges (for overflow from add/sub)
725 0     0   0 my $self = shift; my $mdon = shift; my $dinf = 0;
  0         0  
  0         0  
726 0 0       0 unless($mdon) {
727 0 0 0     0 if($self->{'_jink'} >= $self->{'__jpf'} || 0 > $self->{'_jink'}) {
728 0 0       0 $self->{'_jink'} -= $self->{'__jpf'} if(0 > $self->{'_jink'});
729 0         0 $self->{'_frame'} += int($self->{'_jink'} / $self->{'__jpf'});
730 0         0 $self->{'_jink'} %= $self->{'__jpf'};
731             }
732 0 0 0     0 if($self->{'_frame'} >= $self->{'__fps'} || 0 > $self->{'_frame'}) {
733 0 0       0 $self->{'_frame'} -= $self->{'__fps'} if(0 > $self->{'_frame'});
734 0         0 $self->{'_second'} += int($self->{'_frame'} / $self->{'__fps'});
735 0         0 $self->{'_frame'} %= $self->{'__fps'};
736             }
737 0 0 0     0 if($self->{'_second'} >= 60 || 0 > $self->{'_second'}) {
738 0 0       0 $self->{'_second'} -= 60 if(0 > $self->{'_second'});
739 0         0 $self->{'_minute'} += int($self->{'_second'} / 60);
740 0         0 $self->{'_second'} %= 60;
741             }
742 0 0 0     0 if($self->{'_minute'} >= 60 || 0 > $self->{'_minute'}) {
743 0 0       0 $self->{'_minute'} -= 60 if(0 > $self->{'_minute'});
744 0         0 $self->{'_hour'} += int($self->{'_minute'} / 60);
745 0         0 $self->{'_minute'} %= 60;
746             }
747 0 0 0     0 if($self->{'_hour'} >= 24 || 0 > $self->{'_hour'}) {
748 0 0       0 $self->{'_hour'} -= 24 if(0 > $self->{'_hour'});
749 0         0 $self->{'_day'} += int($self->{'_hour'} / 24);
750 0         0 $self->{'_hour'} %= 24;
751             }
752 0 0 0     0 $dinf = 1 unless(defined($self->{'_month'}) && $self->{'_month'});
753 0 0       0 $self->{'_month'} = 1 if($dinf);
754 0   0     0 while($self->{'_day'} > days_in($self->Y, $self->M) || 0 > $self->{'_day'}) {
755 0 0       0 if(0 >= $self->{'_day'}) {
756 0         0 $self->{'_month'}--;
757 0         0 while($self->{'_month'} < 1) {
758 0         0 $self->{'_year'}--;
759 0         0 $self->{'_month'} += 12;
760             }
761 0         0 $self->{'_day'} += days_in($self->Y, $self->M);
762             } else {
763 0         0 $self->{'_day'} -= days_in($self->Y, $self->M);
764 0         0 $self->{'_month'}++;
765 0         0 while($self->{'_month'} > 12) {
766 0         0 $self->{'_year'}++;
767 0         0 $self->{'_month'} -= 12;
768             }
769             }
770             }
771 0 0       0 $self->{'_month'}-- if($dinf);
772             } else {
773 0 0 0     0 if($self->{'_month'} > 12 || 0 >= $self->{'_month'}) {
774 0 0       0 $self->{'_month'} -= 12 if(0 > $self->{'_month'});
775 0         0 $self->{'_year'} += int($self->{'_month'} / 12);
776 0         0 $self->{'_month'} %= 12;
777             }
778             # if __use_century && _year > 1000...
779             }
780             }
781              
782             # BEGIN legacy `pt` util code
783             my $numb; my $rslt; my $temp;
784             #my @dayo = qw(Sun Mon Tue Wed Thu Fri Sat Sha);
785             #my @mnth = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
786             my @dayo = Time::DayOfWeek::DayNames();
787             my @mnth = Time::DayOfWeek::MonthNames();
788             foreach(@dayo) { $_ = substr($_, 0, 3) if(length($_) > 3); }
789             foreach(@mnth) { $_ = substr($_, 0, 3) if(length($_) > 3); }
790             my %dmap = (); for(my $i=1; $i<=@dayo; $i++) { $dmap{lc($dayo[$i-1])} = $i; }
791             my %mmap = (); for(my $i=1; $i<=@mnth; $i++) { $mmap{lc($mnth[$i-1])} = $i; }
792              
793             sub Pt2Epoch { # converts passed val either to epoch or pt depending
794 0   0 0 0 0 $numb = shift || return(0); my $ptoe = ""; my $yeer = 0; my @prtz = ();
  0         0  
  0         0  
  0         0  
795 0 0 0     0 if (0 < length($numb) && length($numb) <= 7) {
    0 0        
796 0         0 @prtz = split(//, $numb); splice(@prtz,7,($#prtz-7)); # chop extras off!
  0         0  
797 0 0       0 for(my $i=0; $i<7; $i++) { unless(defined($prtz[$i])) { $prtz[$i] = 0; } }
  0         0  
  0         0  
798 0 0       0 $prtz[1]-- if($prtz[1]);
799 0 0       0 $prtz[2] = 1 unless($prtz[2]);
800 0         0 @prtz = (b10($prtz[5]), b10($prtz[4]), b10($prtz[3]),
801             b10($prtz[2]), b10($prtz[1]), b10($prtz[0]));
802             #print "@prtz \n";
803 0         0 $ptoe = timelocal(@prtz);
804             } elsif(7 < length($numb) && length($numb) <= 12) {
805 0         0 @prtz = localtime($numb);
806 0         0 @prtz = (b64(int(($prtz[5]-101)*12)+$prtz[4]+1), b64($prtz[3]),
807             b64($prtz[2]), b64($prtz[1]), b64($prtz[0]));
808 0 0       0 for(my $i = 0; $i < 6; $i++) { $ptoe .= $prtz[$i] if defined($prtz[$i]); }
  0         0  
809             }
810 0         0 return($ptoe);
811             }
812              
813             sub PtCmpPt { # compares two pt's, returns "lt", "eq", "gt", || "ne" if parmerr
814             # need year logic to handle exceptions to ordered field progression
815 0   0 0 0 0 my $numa = shift || return("ne"); $numb = shift || return("ne");
  0   0     0  
816 0         0 my $prsl = "eq"; my @prta = split(//, $numa); my @prtb = split(//, $numb);
  0         0  
  0         0  
817 0         0 for (my $i=0; $i<7; $i++) {
818 0 0       0 if($prsl eq "eq") {
819 0 0 0     0 if (($i < @prtb) && (($i == @prta) ||
    0 0        
      0        
      0        
820             (b10($prta[$i]) < b10($prtb[$i])))) {
821 0         0 $prsl = "lt";
822             } elsif(($i < @prta) && (($i == @prtb) ||
823             (b10($prta[$i]) > b10($prtb[$i])))) {
824 0         0 $prsl = "gt";
825             }
826             }
827             }
828             #if ($numa lt $numb) { $prsl = "lt"; } elsif($numa gt $numb) { $prsl = "gt"; } else { $prsl = "eq"; }
829 0         0 return($prsl);
830             }
831              
832             sub pt {
833 0     0 1 0 my @parm = split(/\s+/, join(' ', @_)); # param
834 0 0 0     0 @parm = split(/\s+/, join(' ', )) if(!@parm && -p STDIN); # pipedin
835 0         0 my $tout = shift(@parm); my $dayv = shift(@parm); my $dowk;
  0         0  
  0         0  
836 0         0 my $colr = 0; my $nwln = 0;
  0         0  
837 0   0     0 while(defined($tout) && $tout =~ s/^-+//) {
838 0 0       0 if ($tout =~ /^c/i) { # escape colored output
    0          
    0          
839 0         0 $colr = 1;
840 0 0       0 $colr = 2 if($tout =~ /^cp/); # colored for zshell prompt
841             } elsif($tout =~ /^n/i) { # append newline option
842 0         0 $nwln = 1;
843             } elsif($tout =~ s/^f//i) { # read input from a file
844 0 0 0     0 if (length($tout) && -r $tout) {
    0 0        
845 0         0 open(INFL, "<$tout");
846 0         0 @parm = split(/\s+/, join(' ', ));
847 0         0 $dayv = shift(@parm);
848 0         0 close(INFL);
849             } elsif(length($dayv) && -r $dayv) {
850 0         0 open(INFL, "<$dayv"); $tout = $dayv; $dayv = shift(@parm);
  0         0  
  0         0  
851 0         0 @parm = split(/\s+/, join(' ', ));
852 0         0 $dayv = shift(@parm);
853 0         0 close(INFL);
854             }
855             }
856 0         0 $tout = $dayv; $dayv = shift(@parm);
  0         0  
857             }
858 0 0 0     0 if ( defined($tout) && defined($dayv) &&
      0        
      0        
      0        
859             exists($dmap{lc($tout)}) &&
860             (exists($mmap{lc($dayv)}) || $dayv =~ /^\d\d?$/)) {
861 0         0 $tout = $dayv; $dayv = shift(@parm); # ignore Day-of-the-Week as first parameter
  0         0  
862             }
863 0         0 my $yerv = shift(@parm);
864 0         0 my $horv = shift(@parm); my $minv = shift(@parm);
  0         0  
865 0         0 my $secv = shift(@parm); my $frmv = shift(@parm);
  0         0  
866 0         0 my @lims = ( [ \$horv, 48 ], [ \$minv, 60 ], [ \$secv, 60 ], [ \$frmv, 60 ]);
867 0 0 0     0 if (defined($yerv) && defined($horv) && $yerv =~ /^\d+:\d+(:\d+)?(:\d+)?$/) {
      0        
868 0         0 ($yerv, $horv) = ($horv, $yerv);
869             }
870 0 0 0     0 if (defined($dayv) && defined($yerv) &&
      0        
      0        
871             ($dayv =~ /^c(mp)?$/i || $yerv =~ /^c(mp)?$/i)) {
872 0 0       0 if ($dayv =~ /^c(mp)?$/i) { $dayv = $yerv; }
  0         0  
873 0         0 $yerv = "c";
874             }
875 0 0 0     0 if(defined($dayv) && defined($yerv) && $dayv =~ /^[+-]$/) {
      0        
876 0         0 $tout .= "$dayv$yerv";
877 0 0       0 if(defined($horv)) {
878 0 0 0     0 if ($horv eq "-e") { $dayv = "-e"; }
  0 0       0  
879             elsif(defined($minv) && $horv =~ /^[+-]$/) {
880 0         0 $tout .= "$horv$minv";
881             }
882             }
883 0 0       0 if(defined($secv)) {
884 0 0       0 if ($secv eq "-e") { $dayv = "-e"; }
  0 0       0  
885             elsif($secv =~ /^[+-]$/) {
886 0         0 $temp = shift(@parm);
887 0 0       0 if(defined($temp)) { $tout .= "$secv$temp"; }
  0         0  
888             }
889             }
890             }
891 0         0 my @time = localtime(); @time = @time[0..5]; my @fldz = (); my $year = 0;
  0         0  
  0         0  
  0         0  
892 0         0 my @stim = (); my $summ = 0; my $oper = 0; my $subs = Time::HiRes::time();
  0         0  
  0         0  
  0         0  
893 0         0 $subs -= int($subs); $subs = int($subs * 60); unshift(@time, $subs);
  0         0  
  0         0  
894 0         0 @time = reverse @time;
895 0 0       0 if(defined($tout)) {
896 0 0       0 $tout = $mmap{lc($tout)} if(exists($mmap{lc($tout)}));
897 0 0       0 if($tout =~ /^(\d\d?)([-\/])(\d\d?)\2(\d{1,4})$/) {
898 0         0 $tout = $1; $dayv = $3; $yerv = $4; # month-day-year
  0         0  
  0         0  
899 0 0       0 $yerv = '0' . $yerv if(length($yerv) == 1);
900 0 0       0 $yerv = '20' . $yerv if(length($yerv) == 2);
901             }
902             }
903 0 0       0 if(!defined($tout)) {
904 0         0 $time[0] -= 100; $time[1]++;
  0         0  
905 0         0 for(my $i = 0; $i < 7; $i++) { $time[$i] = b64($time[$i]); }
  0         0  
906             }
907 0 0 0     0 if((defined($tout) && $tout =~ /^(\w+)([+-].+)$/)) { # add/sub pt
    0          
908             #print "$tout=";
909 0         0 $summ = $1; $tout = $2;
  0         0  
910 0 0       0 $summ = Pt2Epoch($summ) if (length($summ) <= 7);
911 0         0 while($tout =~ /^([+-])(\w+)/) {
912 0         0 $oper = $2; while(length($oper) < 7) { $oper .= "0"; }
  0         0  
  0         0  
913 0         0 @fldz = split(//, reverse($oper));
914 0         0 @stim = localtime($summ);
915 0 0       0 if ($1 eq "+") {
916 0         0 $stim[0] += b64($fldz[0]);
917 0         0 while ($stim[0] > 59) { $stim[1]++; $stim[0] -= 60; }
  0         0  
  0         0  
918 0         0 $stim[1] += b64($fldz[1]);
919 0         0 while ($stim[1] > 59) { $stim[2]++; $stim[1] -= 60; }
  0         0  
  0         0  
920 0         0 $stim[2] += b64($fldz[2]);
921 0         0 while ($stim[2] > 59) { $stim[3]++; $stim[2] -= 60; }
  0         0  
  0         0  
922 0         0 $stim[3] += b64($fldz[3]);
923 0         0 while ($stim[2] > 23) { $stim[3]++; $stim[2] -= 24; }
  0         0  
  0         0  
924 0         0 $stim[3] += b64($fldz[3]);
925 0         0 while ($stim[3] > days_in($stim[5], $stim[4])) {
926 0 0 0     0 if ($stim[3] != 29 || $stim[4] != 1 || ($stim[5]%4) != 0) {
    0 0        
927 0         0 $stim[3] -= days_in($stim[5], $stim[4]); $stim[4]++;
  0         0  
928             } elsif ($stim[3] > 29) { # ck leap year
929 0         0 $stim[3] -= 29; $stim[4]++;
  0         0  
930             }
931             }
932 0         0 $stim[4] += (b10($fldz[4])+11)%12 + 1;
933 0 0       0 while ($stim[4] > 11) { $stim[4] -= 12; $stim[5]++ if $fldz[4]; }
  0         0  
  0         0  
934 0         0 $stim[5] += int((b10($fldz[4])-1)/12);
935             } else {
936 0         0 $stim[0] -= b10($fldz[0]);
937 0         0 while ($stim[0] < 0) { $stim[1]--; $stim[0] += 60; }
  0         0  
  0         0  
938 0         0 $stim[1] -= b10($fldz[1]);
939 0         0 while ($stim[1] < 0) { $stim[2]--; $stim[1] += 60; }
  0         0  
  0         0  
940 0         0 $stim[2] -= b10($fldz[2]);
941 0         0 while ($stim[2] < 0) { $stim[3]--; $stim[2] += 24; }
  0         0  
  0         0  
942 0         0 $stim[3] -= b10($fldz[3]);
943 0         0 while ($stim[3] < 0) {
944 0 0 0     0 if ($stim[4] != 2 || ($stim[5]%4) != 0) {
945 0         0 $stim[4]--; $stim[3] += days_in($stim[5], $stim[4]);
  0         0  
946             } else { # ck leap year
947 0         0 $stim[4]--; $stim[3] += 29;
  0         0  
948             }
949             }
950 0         0 $stim[4] -= (b10($fldz[4])+11)%12 + 1;
951 0 0       0 while ($stim[4] < 0) { $stim[4] += 12; $stim[5]-- if $fldz[4]; }
  0         0  
  0         0  
952 0         0 $stim[5] -= int((b10($fldz[4])-1)/12);
953             }
954 0 0       0 if (!$stim[3]) { $stim[3]++; } # adding a day to 0-days
  0         0  
955 0         0 $summ = timelocal(@stim);
956 0         0 $tout =~ s/^[+-]\w+//;
957             }
958 0 0 0     0 if(defined($dayv) && $dayv =~ /^(-e|d)$/) { $rslt = $summ; }
  0         0  
959 0         0 else { $rslt = Pt2Epoch($summ); }
960             #print " ", $summ;
961             #print " ", scalar localtime($summ);
962             } elsif(defined($tout)) { # turn expanded date parameters into equiv pt
963 0 0       0 $tout = $mmap{lc($tout)} if(exists($mmap{lc($tout)}));
964 0 0 0     0 if ($tout eq "-e" || (defined($dayv) && $dayv eq "-e")) { # cnv pt2ep
    0 0        
    0 0        
      0        
      0        
      0        
965             # ($tout, $dayv) = ($dayv, $tout) if(defined $dayv && $dayv eq "-e");
966 0 0 0     0 if ($tout eq "pt" || $tout eq "-e") { $rslt = scalar Time::HiRes::time(); }
  0 0       0  
967 0         0 elsif(length($tout) > 7) { $rslt = scalar localtime($tout); }
968 0         0 else { $rslt = Pt2Epoch($tout); }
969             } elsif($tout eq "pt") {
970 0         0 $dowk = Time::DayOfWeek::Dow($time[0] + 1900, $time[1] + 1, $time[2]);
971 0         0 $rslt = sprintf("%s %s %2s %02d:%02d:%02d:%02d %4d",
972             $dowk, $mnth[($time[1] % @mnth)], $time[2], $time[3],
973             $time[4], $time[5], $time[6], $time[0] + 1900);
974             } elsif(defined($dayv) && length($dayv) && length($tout) &&
975             defined($yerv) && $yerv eq "c") { # compare two pt's
976 0         0 $rslt = PtCmpPt($tout, $dayv);
977             } else { # normal pt decoding
978 0         0 @time = split(//, $tout); @time = @time[0..6]; # chop extras off!
  0         0  
979 0         0 for(my $i=0; $i<7; $i++) {
980 0 0       0 if(defined($time[$i])) { $time[$i] = b10($time[$i]); }
  0         0  
981 0         0 else { $time[$i] = 0; }
982             }
983             # 0) Each 12 added to the Month adds 64 to the Year.
984             # 1) 24 added to the Hour adds 320 to the Year.
985             # 2) 31 added to the Day makes the year negative just before adding 2k
986 0 0       0 $time[1]-- if($time[1]); # 0-base month
987 0 0       0 $time[2]++ unless($time[2]); # 1-base day
988 0         0 $time[1] %= 60; # 5 month blocks go 0-59 (0-11,12-23,24-35,36-47,48-59)
989 0 0       0 $time[2] = 1 if($time[2] > 62); # day blocks go 1..62 (1..31, 32..62)
990 0         0 $time[3] %= 48; # hour blocks go 0..47 (0..23, 24..47)
991 0         0 $time[4] %= 60; $time[5] %= 60; $time[6] %= 60; # min,sec,60th all 0..59
  0         0  
  0         0  
992 0         0 while($time[1] > 11) { $time[0] += 64; $time[1] -= 12; }
  0         0  
  0         0  
993 0 0       0 if ($time[3] > 23) { $time[0] += 320; $time[3] -= 24; }
  0         0  
  0         0  
994 0 0       0 if ($time[2] > 31) { $time[0] *= -1; $time[2] -= 31; }
  0         0  
  0         0  
995             #print "tout:$tout\ntime:@time\n";
996 0         0 $time[0] += 100;
997 0         0 $dowk = Time::DayOfWeek::Dow($time[0] + 1900, $time[1] + 1, $time[2]);
998 0         0 $rslt = sprintf("%s %s %2s %02d:%02d:%02d:%02d %4d",
999             $dowk, $mnth[($time[1] % @mnth)], $time[2], $time[3],
1000             $time[4], $time[5], $time[6], $time[0] + 1900);
1001             }
1002             } else { # normal pt encoding
1003 0 0       0 if($colr) {
1004 0 0       0 if($colr == 2) {
1005 0         0 $rslt = "%{\e[1;31m%}$time[0]" .
1006             "%{\e[0;33m%}$time[1]" .
1007             "%{\e[1;33m%}$time[2]" .
1008             "%{\e[32m%}$time[3]" .
1009             "%{\e[36m%}$time[4]" .
1010             "%{\e[34m%}$time[5]" .
1011             "%{\e[35m%}$time[6]";
1012             } else {
1013 0         0 $rslt = "\e[1;31m$time[0]" .
1014             "\e[0;33m$time[1]" .
1015             "\e[1;33m$time[2]" .
1016             "\e[32m$time[3]" .
1017             "\e[36m$time[4]" .
1018             "\e[34m$time[5]" .
1019             "\e[35m$time[6]";
1020             }
1021             } else {
1022 0         0 $rslt = join('', @time);
1023             }
1024             #$temp = join('', @time); print "\n", `cnv $temp 64 128`, "\n", `cnv $temp 64 10`;
1025             } # print "\n"; # hmmm...
1026 0 0       0 $rslt .= "\n" if($nwln);
1027 0         0 return($rslt);
1028             }
1029             # END legacy `pt` util code
1030              
1031             sub ptcc { # Generic PipTime Curses::Simp Color Code strings as class method
1032 0   0 0 1 0 my $frmt = shift || 0; my $ptst;
  0         0  
1033 0 0       0 if ($frmt =~ /^-*f/i) {
    0          
1034 0         0 $ptst = '!YYY OOO YY GGWCCWUUWPP RRRR';
1035             #`pt pt`->Wed Jul 16 00:03:31:30 2003
1036             } elsif($frmt =~ /^-*k/i) {
1037 0         0 $ptst = '!ROYuX3GCUP'; # same as below but with 'hms' in blue bkgrnd
1038             } else {
1039 0         0 $ptst = '!ROYGCUP'; #'.bROYGCUP.';
1040             # `pt`-> YMDhmsf YMDhmsf
1041             }
1042 0         0 return($ptst);
1043             }
1044              
1045             # returns a PT object's expanded string form
1046             sub expand {
1047 0     0 0 0 my $self = shift;
1048 0         0 return(sprintf("%3s %3s %2d %02d:%02d:%02d:%02d %4d",
1049             # Time::DayOfWeek::Dow($self->YMD),
1050             $self->Dow(),
1051             $mnth[$self->month() - 1],
1052             $self->day(),
1053             $self->hour(),
1054             $self->minute(),
1055             $self->second(),
1056             $self->frame(),
1057             $self->year()));
1058             }
1059              
1060             # adds color codes corresponding to each field according to ColorTYPe
1061             # (/^s/i) ? Curses::Simp color codes
1062             # : (/^h/i) ? HTML links && font color tag delimiters
1063             # : (/^4/i) ? 4NT verbose color codes
1064             # : ANSI color escapes (/^z/i) ? wrapped in zsh delimiters;
1065             sub _color_fields {
1066 0     0   0 my $self = shift;
1067 0 0 0     0 my $fstr = shift || ' ' x 10; $fstr =~ s/0+$// if(length($fstr) <= 7);
  0         0  
1068 0   0     0 my $ctyp = shift || 'ANSI';
1069 0         0 my @clrz = (); my $coun = 0; my $rstr = '';
  0         0  
  0         0  
1070 0 0       0 if ($ctyp =~ /^s/i) { # simp color codes
    0          
    0          
1071 0         0 @clrz = @{$self->_field_colors('simp')};
  0         0  
1072 0 0       0 if(length($fstr) > 7) {
1073 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[$coun++]; }
  0         0  
1074             } else {
1075 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[(1 + $coun++)]; }
  0         0  
1076             }
1077             } elsif($ctyp =~ /^h/i) { # HTML link && font color tag delimiters
1078 0         0 @clrz = @{$self->_field_colors('html')};
  0         0  
1079 0         0 $_ = '' foreach(@clrz);
1080 0         0 $rstr = '';
1081 0 0       0 if(length($fstr) > 7) {
1082 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[$coun] . substr($fstr, $coun++, 1) . ''; }
  0         0  
1083             } else {
1084 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[(1 + $coun)] . substr($fstr, $coun++, 1) . ''; }
  0         0  
1085             }
1086 0         0 $rstr .= '';
1087             } elsif($ctyp =~ /^4/i) { # 4NT prompt needs verbose color codes
1088 0         0 @clrz = @{$self->_field_colors('4nt')};
  0         0  
1089 0         0 for(my $i=0; $i<@clrz; $i++) {
1090 0         0 $clrz[$i] = ' & color ' . $clrz[$i] . ' & echos ';
1091             }
1092 0 0       0 if(length($fstr) > 7) {
1093 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[$coun] . substr($fstr, $coun++, 1); }
  0         0  
1094             } else {
1095 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[(1 + $coun)] . substr($fstr, $coun++, 1); }
  0         0  
1096             }
1097             } else { # ANSI escapes
1098 0         0 @clrz = @{$self->_field_colors('ansi')};
  0         0  
1099 0 0       0 if($ctyp =~ /^z/i) { # zsh prompt needs delimited %{ ANSI %}
1100 0         0 for(my $i=0; $i<@clrz; $i++) { $clrz[$i] = '%{' . $clrz[$i] . '%}'; }
  0         0  
1101             }
1102 0 0       0 if(length($fstr) > 7) {
1103 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[$coun] . substr($fstr, $coun++, 1); }
  0         0  
1104             } else {
1105 0         0 while(length($fstr) > $coun) { $rstr .= $clrz[(1 + $coun)] . substr($fstr, $coun++, 1); }
  0         0  
1106             }
1107             }
1108 0         0 return($rstr);
1109             }
1110              
1111             # Time::PT object constructor as class method or copy as object method.
1112             # First param can be ref to copy. Not including optional ref from
1113             # copy, default is no params to create a new empty PT object.
1114             # If params are supplied, they must be a single key && a single value.
1115             # The key must be one of the following 3 types of constructor
1116             # initialization mechanisms:
1117             # -1) (eg. '3C79jo0')
1118             # 0) 'str' => (eg. 'str' => '0123456789')
1119             # 1) 'list' => (eg. 'list' => [0, 1, 2..9])
1120             # 2) 'hash' => (eg. 'hash' => {'jink' => 8})
1121             sub new {
1122 7     7 1 686 my ($nvkr, $ityp, $idat) = @_;
1123 7         20 my $nobj = ref($nvkr);
1124 7         18 my $clas = $ityp;
1125 7 50 33     85 $clas = $nobj || $nvkr if(!defined($ityp) || $ityp !~ /::/);
      66        
1126 7         52 my $self = Time::Fields->new($clas);
1127 7         18 my $rgxs; my $mont; my @attz = $self->_attribute_names();
  7         24  
1128             # timelocal($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
1129 7         393 my @ltim = localtime(); my $subs = Time::HiRes::time(); $subs -= int($subs);
  7         38  
  7         18  
1130 7         23 $self->{'_year'} = $ltim[5] + 1900;
1131 7         15 $self->{'_month'} = $ltim[4] + 1;
1132 7         13 $self->{'_day'} = $ltim[3];
1133 7         10 $self->{'_hour'} = $ltim[2];
1134 7         15 $self->{'_minute'} = $ltim[1];
1135 7         15 $self->{'_second'} = $ltim[0];
1136 7         41 $self->{'_frame'} = int($subs * $self->{'__fps'});
1137             #$subs *= $self->{'__fps'}; $subs -= int($subs);
1138             #$self->{'_jink'} = int($subs * $self->{'__jpf'});
1139 7         23 $self->{'__time_separator'} = ':';
1140 7         15 $self->{'__date_separator'} = '-';
1141 7         14 foreach my $attr ( @attz ) {
1142             # $self->{$attr} = $self->_default_value($attr); # init defaults
1143 154 50       245 $self->{$attr} = $nvkr->{$attr} if($nobj); # && copy if supposed to
1144             }
1145 7 100 66     52 if(defined($ityp) && $ityp !~ /::/) { # there were initialization params
1146 5         10 foreach my $attr ( @attz ) {
1147 110         307 $self->{$attr} = $self->_default_value($attr); # init defaults
1148             }
1149 5 100       17 ($ityp, $idat) = ('str', $ityp) unless(defined($idat));
1150 5 100 66     43 if($ityp =~ /^verbose$/i) { # handle 'verbose' differently
    50          
1151             # verbose string param is expanded date &&/or time text
1152 1         12 $rgxs = '^\\s*((' . join('|', @dayo) . ')\\S*)?\\s*(' .
1153             join('|', @mnth) . ')\\S*\\s*(\\d+)' .
1154             '\\s+(\\d+(\D+(\\d+)){0,4})\\s+(\d+)\\s*$';
1155 1 50       191 if($idat =~ /$rgxs/i) {
1156             #print "idat:$idat\nrgxs:$rgxs\nDow?$2 Mon$3 dy$4 hr:mn?:sc?:fr?:jn?$5 YEAR!\n";
1157 0         0 $mont = $3;
1158 0         0 $self->{'_day'} = $4;
1159 0         0 ($self->{'_hour'} ,
1160             $self->{'_minute'},
1161             $self->{'_second'},
1162             $self->{'_frame'} ,
1163             $self->{'_jink'} ) = split(/\D+/, $5);
1164 0         0 $self->{'_year'} = $8;
1165             #print "M:$mont D:$self->{'_day'} h:($self->{'_hour'} m:$self->{'_minute'} s:$self->{'_second'} f:$self->{'_frame'} j:($self->{'_jink'} Y:$self->{'_year'}\n";
1166             } else {
1167 1         8 $rgxs = '^\\s*((' . join('|', @dayo) . ')\\S*)?\\s*(' .
1168             join('|', @mnth) . ')\\S*\\s*(' .
1169             '\\d+)\\s*,?\\s*(\\d+)\\s*$';
1170 1 50       113 if($idat =~ /$rgxs/i) {
1171             #print "Dow?$2 " if(defined($2)); print "Mon$3 dy$4 YEAR$5!\n";
1172 1         5 $mont = $3;
1173 1         4 $self->{'_day'} = $4;
1174 1         4 $self->{'_year'} = $5;
1175             } else {
1176 0         0 $rgxs = '^\\s*(\\d+(\D+(\\d+)){0,4})\\s*$';
1177 0 0       0 if($idat =~ /$rgxs/i) {
1178 0         0 print "hr:mn?:sc?:fr?:jn?!\n";
1179             # 2do: continue testing && assigning all acceptable verbose formats
1180             }
1181             }
1182             }
1183 1 50       15 if(defined($mont)) { # convert named month to proper index number
1184 1         4 for(my $i = 0; $i < @mnth; $i++) { # find which month name
1185 12 100       38 if(lc($mont) eq lc($mnth[$i])) { # $mont =~ /^$mnth[$i]/i) {
1186 1         5 $self->{'_month'} = ($i + 1); # ($i + 1) for 1-based month field
1187             }
1188             }
1189             }
1190             } elsif($ityp =~ /^s/i && length($idat) <= 9) { # handle small 'str' differently
1191             # small str param grows right from year field
1192 0         0 my $ilen = length($idat);
1193 0         0 for(my $i = 1; $i <= $ilen; $i++) {
1194 0 0       0 if($idat =~ s/^(.)//) {
1195 0         0 $self->{$attz[$i]} = b10($1); # break down str
1196             }
1197             }
1198 0         0 $self->{'_year'} += 2000;
1199             } else {
1200 4         9 foreach my $attr ( @attz ) {
1201 88 100       9732 if ($ityp =~ /^s/i) { # 'str'
    100          
    50          
1202 44 100       264 $self->{$attr} = b10($1) if($idat =~ s/^(.)//); # break down string
1203             } elsif($ityp =~ /^[la]/i) { # 'list' or 'array'
1204 22 100       121 $self->{$attr} = shift( @{$idat} ) if(@{$idat}); # shift list vals
  10         27  
  22         149  
1205             } elsif($ityp =~ /^h/i) { # 'hash'
1206             # do some searching to find hash key that matches
1207 22         23 foreach(keys(%{$idat})) {
  22         60  
1208 9 100       179 if($attr =~ /$_/) {
1209 1         3 $self->{$attr} = $idat->{$_};
1210 1         5 delete($idat->{$_});
1211             }
1212             }
1213             } else { # undetected init type
1214 0         0 croak "!*EROR*! PT::new initialization type: $ityp did not match 'str', 'list', or 'hash'!\n";
1215             }
1216             }
1217             }
1218             }
1219 7         21 foreach my $attr ( @attz ) { # init defaults for any undefined fields
1220 154 50       416 $self->{$attr} = $self->_default_value($attr) unless(defined($self->{$attr}));
1221             }
1222             # Handle Year shifts
1223 7         26 $self->{'_year'} -= 2000;
1224             # 0) Each 12 added to the Month adds 64 to the Year.
1225             # 1) 24 added to the Hour adds 320 to the Year.
1226             # 2) 31 added to the Day makes the year negative just before adding 2k
1227 7 100       11 my $mdec = 0; $mdec = 1 if($self->{'_month'});
  7         26  
1228 7 100       23 $self->{'_month'}-- if($mdec); # 0-base month
1229 7 100       15 my $dinc = 0; $dinc = 1 unless($self->{'_day'});
  7         22  
1230 7 100       19 $self->{'_day'}++ if($dinc); # 1-base day
1231             # 5 month blocks go 0..59 (0..11,12..23,24..35,36..47,48..59)
1232 7         17 $self->{'_month'} %= 60;
1233             # day blocks go 1..62 (1..31, 32..62)
1234 7 50       20 $self->{'_day'} = 1 if($self->{'_day'} > 62);
1235             # hour blocks go 0..47 (0..23, 24..47)
1236 7         12 $self->{'_hour'} %= 48;
1237             # min,sec,frm,jnk all 0..59
1238 7         14 $self->{'_minute'} %= 60; $self->{'_second'} %= 60;
  7         12  
1239 7         12 $self->{'_frame'} %= 60; $self->{'_jink'} %= 60;
  7         11  
1240 7         29 while($self->{'_month'} > 11) {
1241 0         0 $self->{'_year'} += 64; $self->{'_month'} -= 12;
  0         0  
1242             }
1243 7 50       27 if ($self->{'_hour'} > 23) {
1244 0         0 $self->{'_year'} += 320; $self->{'_hour'} -= 24;
  0         0  
1245             }
1246 7 50       21 if ($self->{'_day'} > 31) {
1247 0         0 $self->{'_year'} *= -1; $self->{'_day'} -= 31;
  0         0  
1248             }
1249 7 100       17 $self->{'_day'}-- if($dinc); # 0-base day again only if inc'd above
1250 7 100       18 $self->{'_month'}++ if($mdec); # 1-base month again only if dec'd above
1251 7         12 $self->{'_year'} += 2000;
1252 7         45 return($self);
1253             }
1254              
1255 0     0 0   sub subsecond { return(frame(@_)); }
1256             sub _mon { # 0-based month
1257 0     0     my ($self, $nwvl) = @_;
1258 0 0         $self->{'_month'} = ($nwvl + 1) if(@_ > 1);
1259 0           return($self->{'_month'} - 1);
1260             }
1261             sub fullmonth { # full month string
1262 0     0 0   my ($self, $nwvl) = @_; my $mtch; my $mret;
  0            
1263 0           my @mnmz = Time::DayOfWeek::MonthNames();
1264 0 0         if(@_ > 1) {
1265 0           for($mtch=0; $mtch<@mnmz; $mtch++) {
1266 0 0         if($mnmz[$mtch] =~ /^$nwvl/i) {
1267 0           $self->{'_month'} = $mtch + 1; last;
  0            
1268             }
1269             }
1270             }
1271 0           $mret = $mnmz[(($self->{'_month'} - 1) % 12)];
1272 0           return($mret);
1273             }
1274             sub monname { # abbreviated month string
1275 0     0 0   my $monr = $_[0]->fullmonth();
1276 0 0         if (@_ > 2) { $monr = $_[ $_[0]->M ]; }
  0 0          
1277 0           elsif(@_ > 1) { $monr = $_[0]->fullmonth($_[1]); }
1278 0 0         $monr = substr($monr, 0, 3) if(length($monr) > 3);
1279 0           return($monr);
1280             }
1281             sub _year { # 1900-based year
1282 0     0     my ($self, $nwvl) = @_;
1283 0 0         $self->{'_year'} = ($nwvl + 1900) if(@_ > 1);
1284 0           return($self->{'_year'} - 1900);
1285             }
1286             sub yy { # 2-digit year
1287 0     0 0   my ($self, $nwvl) = @_; my $yret;
  0            
1288 0 0         if(@_ > 1) {
1289 0 0         ($nwvl >= 70) ? $self->{'_year'} = '19' . $nwvl :
1290             $self->{'_year'} = '20' . $nwvl;
1291             }
1292 0           $yret = sprintf("%04d", $self->{'_year'});
1293 0           return(substr($self->{'_year'}, 2, 2));
1294             }
1295             sub dow { # index of day of week
1296 0     0 0   my ($self, $nwvl) = @_;
1297 0           return(Time::DayOfWeek::DoW($self->YMD));
1298             }
1299             sub Dow { # abbrev. day name
1300 0     0 0   my ($self, $nwvl) = @_;
1301 0           return(Time::DayOfWeek::Dow($self->YMD));
1302             }
1303             sub DayOfWeek { # full day name
1304 0     0 0   my ($self, $nwvl) = @_;
1305 0           return(Time::DayOfWeek::DayOfWeek($self->YMD));
1306             }
1307             *day_of_week = \&dow;
1308             *_wday = \&dow;
1309 0     0 0   sub wday { return(dow(@_) + 1); }
1310             sub wdayname {
1311 0 0   0 0   return($_[ $_[0]->wday ]) if(@_ > 2);
1312 0           return(Dow(@_));
1313             }
1314             #*day = \&Dow; # let day be day-of-month rather than Time::Piece wk-day
1315             *fullday = \&DayOfWeek;
1316             sub yday { # day of year
1317 0     0 0   my ($self, $nwvl) = @_; my $summ = 0;
  0            
1318 0 0         if(@_ > 1) {
1319 0           for(my $m=1; $m<12; $m++) {
1320 0 0         if(($summ + days_in($self->{'_year'}, $m)) > $nwvl) {
1321 0           $self->{'_month'} = $m;
1322 0           $self->{'_day'} = $nwvl - $summ;
1323 0           last;
1324             } else {
1325 0           $summ += days_in($self->{'_year'}, $m);
1326             }
1327             }
1328 0           $summ = $nwvl;
1329             } else {
1330 0           for(my $m=1; $m<$self->{'_month'}; $m++) {
1331 0           $summ += days_in($self->{'_year'}, $m);
1332             }
1333 0           $summ += ($self->{'_day'} - 1);
1334             }
1335             # following compares my yday calculation to localtime's
1336             #my @ltdt = localtime(timelocal($self->smhD, $self->_mon, $self->Y));
1337             #print "!EROR!summ:$summ != ltdt:" . $ltdt[-2] . "\n" if($summ != $ltdt[-2]);
1338             #print join('', $self->smhD) . $self->_mon . ($self->Y - 1900) . "\n" . join('', @ltdt) . "\n";
1339 0           return($summ);
1340             }
1341             *day_of_year = \&yday;
1342             # isdst should be computed by formula when I figure out how so that it
1343             # won't be restricted by UTC range that localtime expects.
1344             sub isdst { # Is Daylight Savings Time?
1345 0     0 0   my ($self, $nwvl) = @_; # need 0-based month as timelocal() param
1346 0           my @ltdt = localtime(timelocal($self->smhD, $self->_mon, $self->Y));
1347 0           return($ltdt[-1]);
1348             }
1349             *daylight_savings = \&isdst;
1350 0     0 0   sub time { return( hmsf( @_)); }
1351 0     0 0   sub alltime { return( hmsfjz(@_)); }
1352 0     0 0   sub date { return( YMD( @_)); }
1353 0     0 0   sub alldate { return(CYMD( @_)); }
1354 0     0 0   sub pt7 { return( YMDhmsf( @_)); }
1355 0     0 1   sub all { return(CYMDhmsfjz(@_)); }
1356             *dt = \&all;
1357             sub datetime { # 2000-02-29T12:34:56 (ISO 8601)
1358 0     0 0   return(sprintf("%04d-%02d-%02dT%02d:%02d:%02d", $_[0]->YMDhms()));
1359             }
1360             *cdate = \&expand;
1361             *compress = \&stringify;
1362             # Add these to pod once imp'd
1363             # $t->epoch # floating point seconds since the epoch
1364             # $t->tzoffset # timezone offset in a Time::Seconds object
1365             #
1366             # $t->julian_day # number of days since Julian period began
1367             # $t->mjd # modified Julian date (JD-2400000.5 days)
1368             #
1369             # $t->week # week number (ISO 8601)
1370             sub epoch { # floating point seconds since the epoch
1371 0     0 1   return(0);
1372             }
1373             sub tzoffset { # timezone offset in a Time::Seconds object
1374 0     0 0   return(0);
1375             }
1376             sub julian_day { # number of days since Julian period began
1377 0     0 0   return(0);
1378             }
1379             sub mjd { # modified Julian date (JD-2400000.5 days)
1380 0     0 0   return(0);
1381             }
1382             sub week { # week number (ISO 8601)
1383 0     0 0   return(0);
1384             }
1385             sub is_leap_year { # true if it its
1386 0     0 0   return(0);
1387             }
1388             sub month_last_day { # 28-31
1389 0     0 0   return(days_in($_[0]->YM));
1390             }
1391             sub time_separator { # set the default separator (default ":")
1392 0 0   0 0   $_[0]->{'__time_separator'} = $_[1] if(@_ > 1);
1393 0           return($_[0]->{'__time_separator'});
1394             }
1395             sub date_separator { # set the default separator (default "-")
1396 0 0   0 0   $_[0]->{'__date_separator'} = $_[1] if(@_ > 1);
1397 0           return($_[0]->{'__date_separator'});
1398             }
1399             sub day_list { # set the default weekdays
1400 0     0 0   my $self = shift;
1401 0           return(Time::DayOfWeek::DayNames(@_));
1402             }
1403             sub mon_list { # set the default months
1404 0     0 0   my $self = shift;
1405 0           return(Time::DayOfWeek::MonthNames(@_));
1406             }
1407              
1408             #sub AUTOLOAD { # methods (created as necessary)
1409             # no strict 'refs';
1410             # my ($self, $nwvl) = @_;
1411             #
1412             # if ($AUTOLOAD =~ /.*::[-_]?([CYMODhmisfjz])(.)?/i) {
1413             # my ($atl1, $atl2) = ($1, $2); my $atnm;
1414             # my @mnmz = Time::DayOfWeek::MonthNames();
1415             # $atl1 = 'O' if($atl1 eq 'm' && defined($atl2) && lc($atl2) eq 'o');
1416             # $atl1 = 'i' if($atl1 eq 'M' && defined($atl2) && lc($atl2) eq 'i');
1417             # $atl1 = 'O' if($atl1 eq 'M');
1418             # $atl1 = 'i' if($atl1 eq 'm');
1419             # $atl1 = 'O' if($AUTOLOAD =~ /.*::fullmon/i);
1420             # foreach my $attr ($self->_attribute_names()){
1421             # my $mtch = $self->_attribute_match($attr);
1422             # $atnm = $attr if(defined($mtch) && $atl1 =~ /$mtch/i);
1423             # }
1424             # if($atl1 eq 'O') {
1425             # if($AUTOLOAD =~ /.*::_/) { # 0-based month
1426             # *{$AUTOLOAD} = sub { $_[0]->{$atnm} = ($_[1] + 1) if(@_ > 1); return($_[0]->{$atnm} - 1); };
1427             # $self->{$atnm} = ($nwvl + 1) if(@_ > 1);
1428             # return($self->{$atnm} - 1);
1429             # } elsif($AUTOLOAD =~ /.*::(full)?mon(th|n)/i) { # abbrev. Mon Name
1430             # if(defined $1) { # store fullmon to do the matching
1431             # *{$AUTOLOAD} = sub {
1432             # my $mtch;
1433             # if(@_ > 1) {
1434             # foreach($mtch=0; $mtch<@mnmz; $mtch++) {
1435             # if($mnmz[$mtch] =~ /^$_[1]/i) {
1436             # $_[0]->{$atnm} = $mtch + 1; last;
1437             # }
1438             # }
1439             # }
1440             # return($mnmz[(($_[0]->{$atnm} - 1) % 12)]);
1441             # };
1442             # } else { # store mon(th|n) as a wrapper that truncs fullmon
1443             # *{$AUTOLOAD} = sub {
1444             # my $monr = $_[0]->fullmonth();
1445             # $monr = $_[0]->fullmonth($_[1]) if(@_ > 1);
1446             # $monr = substr($monr, 0, 3) if(length($monr) > 3);
1447             # return($monr);
1448             # };
1449             # }
1450             # my $mtch; my $mret;
1451             # if(@_ > 1) {
1452             # for($mtch=0; $mtch<@mnmz; $mtch++) {
1453             # if($mnmz[$mtch] =~ /^$nwvl/i) {
1454             # $self->{$atnm} = $mtch + 1; last;
1455             # }
1456             # }
1457             # }
1458             # $mret = $mnmz[(($self->{$atnm} - 1) % 12)];
1459             # if($AUTOLOAD !~ /.*::full/i && length($mret) > 3) {
1460             # $mret = substr($mret, 0, 3);
1461             # }
1462             # return($mret);
1463             # }
1464             # }
1465             # # normal set_/get_ methods
1466             #
1467             # if ($AUTOLOAD =~ /.*::[sg]et(_\w+)/i) {
1468             # my $atnm = lc($1);
1469             # *{$AUTOLOAD} = sub { $_[0]->{$atnm} = $_[1] if(@_ > 1); return($_[0]->{$atnm}); };
1470             # $self->{$atnm} = $nwvl if(@_ > 1);
1471             # return($self->{$atnm});
1472             # # use_??? to set/get field filters
1473             # } elsif($AUTOLOAD =~ /.*::(use_\w+)/i) {
1474             # my $atnm = '__' . lc($1);
1475             # *{$AUTOLOAD} = sub { $_[0]->{$atnm} = $_[1] if(@_ > 1); return($_[0]->{$atnm}); };
1476             # $self->{$atnm} = $nwvl if(@_ > 1);
1477             # return($self->{$atnm});
1478             # # Alias methods which must be detected before sweeps
1479             # } elsif($AUTOLOAD =~ /.*::time$/i) {
1480             # *{$AUTOLOAD} = sub { return($self->hms()); };
1481             # return($self->hms());
1482             # } elsif($AUTOLOAD =~ /.*::dt$/i) {
1483             # *{$AUTOLOAD} = sub { return($self->CYMDhmsfjz()); };
1484             # return($self->CYMDhmsfjz());
1485             # } elsif($AUTOLOAD =~ /.*::mday$/i) { my $atnm = '_day';
1486             # *{$AUTOLOAD} = sub { $_[0]->{$atnm} = $_[1] if(@_ > 1); return($_[0]->{$atnm}); };
1487             # $self->{$atnm} = $nwvl if(@_ > 1); return($self->{$atnm});
1488             # # all joint field methods (eg. YMD(), hms(), foo(), etc.
1489             # } elsif($AUTOLOAD =~ /.*::([CYMODhmisfjz][CYMODhmisfjz]+)$/i) {
1490             # my @fldl = split(//, $1);
1491             # my ($self, @nval) = @_; my @rval = (); my $atnm = ''; my $rgex;
1492             # # handle Month / minute exceptions
1493             # for(my $i=0; $i<$#fldl; $i++) {
1494             # $fldl[$i + 1] = 'O' if($fldl[$i] =~ /[yd]/i && $fldl[$i + 1] eq 'm');
1495             # $fldl[$i ] = 'O' if($fldl[$i] eq 'm' && $fldl[$i + 1] =~ /[yd]/i);$ $fldl[$i ] = 'O' if($fldl[$i] eq 'M');
1496             # $fldl[$i ] = 'i' if($fldl[$i] eq 'm');
1497             # }
1498             # *{$AUTOLOAD} = sub {
1499             # my ($self, @nval) = @_; my @rval = ();
1500             # for(my $i=0; $i<@fldl; $i++) {
1501             # foreach my $attr ($self->_attribute_names()){
1502             # my $mtch = $self->_attribute_match($attr);
1503             # if(defined($mtch) && $fldl[$i] =~ /^$mtch/i) {
1504             # $self->{$attr} = $nval[$i] if($i < @nval);
1505             # push(@rval, $self->{$attr});
1506             # }
1507             # }
1508             # }
1509             # return(@rval);
1510             # };
1511             # for(my $i=0; $i<@fldl; $i++) {
1512             # foreach my $attr ($self->_attribute_names()){
1513             # my $mtch = $self->_attribute_match($attr);
1514             # if(defined($mtch) && $fldl[$i] =~ /$mtch/i) {
1515             # $self->{$attr} = $nval[$i] if($i < @nval);
1516             # push(@rval, $self->{$attr});
1517             # }
1518             # }
1519             # }
1520             # return(@rval);
1521             # # sweeping matches to handle partial keys
1522             # } elsif($AUTOLOAD =~ /.*::[-_]?([CYMODhmisfjz])(.)?/i) {
1523             # my ($atl1, $atl2) = ($1, $2); my $atnm;
1524             # $atl1 = 'O' if($atl1 eq 'm' && defined($atl2) && lc($atl2) eq 'o');
1525             # $atl1 = 'i' if($atl1 eq 'M' && defined($atl2) && lc($atl2) eq 'i');
1526             # $atl1 = 'O' if($atl1 eq 'M');
1527             # $atl1 = 'i' if($atl1 eq 'm');
1528             # foreach my $attr ($self->_attribute_names()) {
1529             # my $mtch = $self->_attribute_match($attr);
1530             # $atnm = $attr if(defined($mtch) && $atl1 =~ /$mtch/i);
1531             # }
1532             # *{$AUTOLOAD} = sub { $_[0]->{$atnm} = $_[1] if(@_ > 1); return($_[0]->{$atnm}); };
1533             # $self->{$atnm} = $nwvl if(@_ > 1);
1534             # return($self->{$atnm});
1535             # } else {
1536             # my $fnam = $AUTOLOAD;
1537             # $fnam =~ s/Time::PT::/Time::Fields::/;
1538             # return(&$fnam);
1539             # croak "No such method: $AUTOLOAD\n";
1540             # }
1541             #}
1542              
1543 0     0     sub DESTROY { } # do nothing but define in case && to calm warning in test.pl
1544              
1545             127;