File Coverage

blib/lib/Convert/NLS_DATE_FORMAT.pm
Criterion Covered Total %
statement 38 38 100.0
branch 12 14 85.7
condition n/a
subroutine 7 7 100.0
pod 2 3 66.6
total 59 62 95.1


line stmt bran cond sub pod time code
1             package Convert::NLS_DATE_FORMAT;
2              
3 3     3   42916 use 5.006;
  3         11  
4 3     3   15 use strict;
  3         6  
  3         99  
5 3     3   23 use warnings;
  3         5  
  3         2549  
6              
7             require Exporter;
8              
9             our @ISA = qw(Exporter);
10             our %EXPORT_TAGS = ( 'all' => [ qw(oracle2posix posix2oracle) ] );
11             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
12             our @EXPORT = qw();
13              
14             our $VERSION = '0.06';
15              
16             our @formats = (
17             [ Q => '%{quarter}' ], # quarter number
18             [ WW => '%U' ], # week number
19             [ IW => '%V' ], # ISO week number
20             [ W => '' ], # week in month
21             [ J => '' ], # Julian days since 31 Dec 4713BC
22             [ YEAR => '' ], # year spelled out
23             [ SYYYY => '%Y' ], # signed year (BC is negative)
24             [ YYYY => '%Y' ], # four digit year
25             [ IYYY => '%G' ], # ISO four digit year
26             [ YYY => '' ], # last three digits of year
27             [ IYY => '' ], # ISO last three digits of year
28             [ YY => '%y' ], # last two digits of year
29             [ IY => '%g' ], # ISO last two digits of year
30             [ RR => '%y' ], # last two digits of year relative to current date
31             [ Month => '%B' ], # month spelled out
32             [ Mon => '%b' ], # three-letter abbreviation month
33             [ MM => '%m' ], # month number
34             [ RM => '' ], # roman numeral month XXII
35             [ DDD => '%j' ], # day of year
36             [ DD => '%d' ], # day of month
37             [ Day => '%A' ], # day of week spelled out
38             [ Dy => '%a' ], # three-letter abbreviation day of week
39             [ D => '%u' ], # day of week
40             [ HH24 => '%H' ], # hours (24)
41             [ HH12 => '%I' ], # hours (12)
42             [ HH => '%I' ], # hours (12)
43             [ MI => '%M' ], # minutes
44             [ SSSSS => '' ], # seconds since midnight
45             [ SS => '%S' ], # seconds
46             [ AM => '%p' ], # displays AM or PM
47             [ PM => '%p' ],
48             [ 'A.M.'=> '' ], # displays A.M. or P.M.
49             [ 'P.M.'=> '' ],
50             [ am => '%P' ], # displays am or pm
51             [ pm => '%P' ],
52             [ 'a.m.'=> '' ], # displays a.m. or p.m.
53             [ 'p.m.'=> '' ],
54             [ BC => '' ], # displays BC or AD
55             [ AD => '' ],
56             [ 'B.C.'=> '' ], # displays B.C. or A.D.
57             [ 'A.D.'=> '' ],
58             [ XFF9 => '.%9N' ], # special case until X can translate to %{decimal}
59             [ XFF6 => '.%6N' ], # special case until X can translate to %{decimal}
60             [ XFF3 => '.%3N' ], # special case until X can translate to %{decimal}
61             [ XFF => '.%6N' ], # special case until X can translate to %{decimal}
62             [ FF => '%6N' ],
63             [ TZHTZM=> '%z' ], # time zone hour offset from UTC
64             [ TZH => '%z' ],
65             [ TZR => '%Z' ], # time zone name
66             [ TH => '' ], # appends 'st', 'nd', 'rd', 'th'
67             [ Y => '' ], # last digit of year
68             [ I => '' ], # ISO last digit of year
69             );
70              
71             my %formats = generate_formats();
72              
73             sub oracle2posix {
74 18     18 1 6329 my ($oracle_format) = @_;
75             # quoted strings require separate processing
76             return join(
77             '',
78 18         58 map { _convert_oracle2posix($_) }
  20         38  
79             split(/(".*?")/, $oracle_format)
80             );
81             }
82              
83             sub _convert_oracle2posix {
84 20     20   30 my ($oracle_format) = @_;
85              
86             # return quoted strings as-is, with the quotes removed
87 20 100       55 return $1 if $oracle_format =~ m/^"(.*?)"$/;
88              
89 19         22 my $string = $oracle_format;
90 19         33 foreach my $pair (@formats) {
91 988         1835 my ($key, $value) = @$pair;
92              
93             # all are case insensitive except am/pm
94 988 100       6721 $key = qr/$key/i unless $key =~ m/^[ap]m$/i;
95              
96             # translate formats found in $oracle_format
97 988 100       10822 if ($string =~ /(?
98 106 100       230 if ($value) {
99 104         1317 $string =~ s/(?
100             } else {
101 2         24 my ($format) = $string =~ /(?
102 2         38 warn "Oracle format '$format' has no POSIX equivalent.\n";
103             }
104             }
105             }
106 19         111 return $string;
107             }
108              
109             sub posix2oracle {
110 11     11 1 3707 my ($format) = @_;
111             # regex from DateTime
112 11         20 $format =~ s/
113             (%\{\w+\})
114             /
115 1 50       7 $formats{$1} ? $formats{$1} : "\%$1"
116             /sgex;
117             # special case for XFF until X can translate to %{decimal}
118 11         27 $format =~ s/
119             (\.%\d?N)
120             /
121 2         8 "XFF"
122             /sgex;
123             # regex from Date::Format
124 11         40 $format =~ s/
125             (%[%a-zA-Z])
126             /
127 60 50       233 $formats{$1} ? $formats{$1} : "\%$1"
128             /sgex;
129 11         42 return $format;
130             }
131              
132             sub generate_formats {
133 3     3 0 6 my %f = ();
134 3         12 foreach my $pair (@formats) {
135 156         228 my ($nls, $posix_format) = @$pair;
136 156 100       317 if ($posix_format) {
137 102         224 $f{$posix_format} = $nls;
138             }
139             }
140 3         6 $f{'%z'} = 'TZHTZM'; # special case
141 3         53 return %f;
142             }
143              
144             1;
145             __END__