package Text::Wigwam::Library::Time;

    use strict;
    use warnings;
    our $VERSION = '0.01';

    use base q/Exporter/;

    use Text::Wigwam::Const qw/ NUM /;

    our %EXPORT_TAGS = (
        all => [
          qw/
            _proto_time       _time
            _proto_gm_time    _gm_time
            _proto_local_time _local_time
          /
        ],
        time       => [ qw/ _proto_time       _time / ],
        gm_time    => [ qw/ _proto_gm_time    _gm_time / ],
        local_time => [ qw/ _proto_local_time _local_time / ],
    );
    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
    our @EXPORT = qw( );

=head1 Name

Text::Wigwam::Library::Time - A Wigwam directive library.

=head1 Description

This library provides directives which are time related.

=head1 Usage

The directives within this library can be imported into specific branches of
the directive tree (which transcends from  C<Text::Wigwam::Directives>) via
plug-ins or modules using one of the following techniques.

 package Text::Wigwam::Directives::some::arbitrary::branch;
 # import everything
 use Text::Wigwam::Library::Time qw/:all/;

 package Text::Wigwam::Directives::another::arbitrary::branch;
 # import selectively
 use Text::Wigwam::Library::Time qw / :time :gm_time :local_time /;

=head1 Directives

=cut

sub _proto_time { [ ] }
sub _time { return time() }

=head2 #time

Returns the epoch time - the number of seconds since January 1, 1970.

 [!!
  #define now #time
  "It's " now
  /* output:
   It's 1113874714
  */
 !!]

=cut

sub _proto_gm_time { [ NUM ] }
sub _gm_time {
    return $_[1] ?
      [ gmtime($_[0]->get_arg) ]
    :
      scalar gmtime($_[0]->get_arg)
    ;
}

=head2 #gm_time I<num>

This is one of the few context-sensitive directives available in the library.
Its behavior depends upon the type of value requested by the directive calling
it. When called in scalar context, it returns a human-readable formatted
string reflecting the given epoch time value, I<num>.

 As of this writing, it's [!! #gm_time #time !!] GMT
 That's a long time since [!! #gm_time 0 !!] GMT
 [!!
  /* output:
   As of this writing, it's Tue Apr 19 01:38:34 2005 GMT
   That's a long time since Thu Jan  1 00:00:00 1970 GMT
  */
 !!]

If called in any non-scalar (array) context, it returns a list which contains
details about the given epoch time, I<num>.

 GM time is [!!
  /* set up some useful data */
  #define days < Sun,Mon,Tue,Wed,Thu,Fri,Sat > 
  #define mons < Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec >
  #macro pad { #ifelse #gt 10 #argv 0 { "0" #argv 0 } #argv 0 }
  /* get the time */
  #define epoch #gm_time #time
  /*
   epoch:0 second
   epoch:1 minute
   epoch:2 hour
   epoch:3 day of the month (1~31)
   epoch:4 month (0-11)
   epoch:5 years since 1900 (add 1900)
   epoch:6 day of the week (0-6/Sun-Sat)
   epoch:7 day of the year (0~365)
   epoch:8 daylight savings time (when true)
  */
 !!]
 [!~ days:[epoch:6] !!] [!! mons:[epoch:4] !!] [!! epoch:3 /* date */ !!]
 [!~ " " &pad epoch:2 ":" &pad epoch:1 ":" &pad epoch:0 /* time of day */ !!]
 [!~ " " #ifelse epoch:8 "DST" "STD" /* daylight savings */ !!]
 [!~ " " #add 1900 epoch:5 /* year */!!]
 [!! 
  /* output:
   GM time is Tue Apr 19 01:38:34 STD 2005
  */
 !!]

=cut

sub _proto_local_time { [ NUM ] }
sub _local_time {
    return $_[1] ?
      [ localtime($_[0]->get_arg) ]
    :
      scalar localtime($_[0]->get_arg)
    ;
}

=head2 #local_time I<num>

Identical to C<#gm_time>, but with the given epoch time corrected for the
local time zone.

 [!! #define time #scalar #local_time #time /* force scalar context */ !!]
 As of this writing, it's [!! time !!] local time
 That's a long time since [!! #local_time 0 !!] local time
 [!!
  /* output:
   As of this writing, it's Mon Apr 18 18:38:34 2005 local time
   That's a long time since Wed Dec 31 16:00:00 1969 local time
  */
 !!]

A non-scalar (array) context example:

 Local time is [!!
  /* set up some useful data */
  #define days < Sun,Mon,Tue,Wed,Thu,Fri,Sat > 
  #define mons < Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec >
  #macro pad {
    #parameters <num>
    #ifelse #gt 10 num { "0" num } num
   } 
  /* get the local time */
  #params < sec min hour mday mon year wday yday dst > #local_time #time
  #join " " (
    wday  mons:[mday] mday /* Calendar date */
    #join ":" (  &pad hour &pad min &pad sec ) /* Time of day */
    #ifelse dst "DST" "STD" /* Daylight savings */
    #add 1900 year /* Year */
   )
  /* output:
   Local time is Mon Apr 18 18:38:34 2005
  */
 !!]

=cut

1;
