File Coverage

blib/lib/DateTime/Format/JSON/MicrosoftDateFormat.pm
Criterion Covered Total %
statement 33 33 100.0
branch 8 8 100.0
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 52 52 100.0


line stmt bran cond sub pod time code
1             package DateTime::Format::JSON::MicrosoftDateFormat;
2 5     5   2028362 use strict;
  5         47  
  5         156  
3 5     5   31 use warnings;
  5         11  
  5         137  
4 5     5   1800 use DateTime;
  5         1001629  
  5         1893  
5              
6             our $VERSION = '0.05';
7             our $PACKAGE = __PACKAGE__;
8              
9             =head1 NAME
10              
11             DateTime::Format::JSON::MicrosoftDateFormat - Parse and format JSON MicrosoftDateFormat strings
12              
13             =head1 SYNOPSIS
14              
15             use DateTime::Format::JSON::MicrosoftDateFormat;
16              
17             my $formatter = DateTime::Format::JSON::MicrosoftDateFormat->new;
18             my $dt = $formatter->parse_datetime("/Date(1392089278000-0600)/"); #2014-02-10T21:27:58Z
19             my $dt = $formatter->parse_datetime("/Date(1392067678000)/"); #2014-02-10T21:27:58Z
20              
21             say $formatter->format_datetime($dt); #/Date(1392067678000)/
22              
23             =head2 The Perl One Liner
24              
25             perl -MDateTime::Format::JSON::MicrosoftDateFormat -e 'print DateTime::Format::JSON::MicrosoftDateFormat->new->parse_datetime(shift), "\n";' '/Date(1392606509000-0500)/'
26              
27             =head1 DESCRIPTION
28              
29             This module understands the JSON MicrosoftDateFormat date/time format. e.g. /Date(1392067678000)/
30              
31             =head1 USAGE
32              
33             Note: The usage of MicrosoftDateFormat is deprecated for new JSON services. Please use ISO 8601 for all new development.
34              
35             From RFC 7493 (The I-JSON Message Format):
36              
37             Protocols often contain data items that are designed to contain timestamps or time durations. It
38             is RECOMMENDED that all such data items be expressed as string values in ISO 8601 format,
39             as specified in RFC 3339, with the additional restrictions that uppercase rather than lowercase
40             letters be used, that the timezone be included not defaulted, and that optional trailing seconds
41             be included even when their value is "00". It is also RECOMMENDED that all data items
42             containing time durations conform to the "duration" production in Appendix A of RFC 3339, with
43             the same additional restrictions.
44              
45             =head2 import
46              
47             Installs the TO_JSON method into the DateTime namespace when requested
48              
49             use DateTime::Format::JSON::MicrosoftDateFormat (to_json => 1); #TO_JSON method installed in DateTime package
50             use DateTime::Format::JSON::MicrosoftDateFormat; #TO_JSON method not installed by default
51              
52             Use the imported DateTime::TO_JSON method and the JSON->convert_blessed options to seamlessly convert DateTime objects to the JSON MicrosoftDateFormat for use in creating encoded JSON structures.
53              
54             use JSON;
55             use DateTime;
56             use DateTime::Format::JSON::MicrosoftDateFormat (to_json=>1);
57             my $formatter = DateTime::Format::JSON::MicrosoftDateFormat->new;
58             my $json = JSON->new->convert_blessed->pretty;
59              
60             my $dt = DateTime->now(formatter=>$formatter);
61             print $json->encode({now=>$dt}); #prints {"now" : "/Date(1392747671000)/"}
62              
63             =cut
64              
65             sub import {
66 7     7   1425 my $self=shift;
67 7 100       69 die("$PACKAGE import: Expecting parameters to be hash") if @_ % 2;
68 5         16 my %opt=@_;
69 5 100       7692 if ($opt{"to_json"}) {
70 1     1   2213 *DateTime::TO_JSON=sub {my $self=shift; return "$self"};
  1         1940  
  1         6  
71             }
72             }
73              
74             =head1 CONSTRUCTOR
75              
76             =head2 new
77              
78             =cut
79              
80             sub new {
81 5     5 1 946 my $class = shift;
82 5         21 return bless {}, $class;
83             }
84              
85             =head1 METHODS
86              
87             =head2 parse_datetime
88              
89             Returns a DateTime object from the given string
90              
91             use DateTime::Format::JSON::MicrosoftDateFormat;
92             my $parser = DateTime::Format::JSON::MicrosoftDateFormat->new;
93             my $dt = $parser->parse_datetime("/Date(1392606509000)/");
94             print "$dt\n";
95              
96             =cut
97              
98             sub parse_datetime {
99 18     18 1 17946 my $self = shift;
100 18         40 my $string = shift;
101             #/Date(1392089278000)/
102             #/Date(1392089278000-0600)/
103             #/Date(1392089278000+0600)/
104 18 100       177 $string =~ m{^/Date\(([+-]?\d+)(?:([+-])(\d\d)(\d\d))?\)/$} or die "Invalid JSON MicrosoftDateFormat string ($string)";
105 15         44 my $milliseconds = $1; #[+-]\d+
106 15         33 my $direction = $2; #[+-]
107 15         29 my $hh = $3; #\d\d
108 15         30 my $mi = $4; #\d\d
109 15         76 my $dt=DateTime->from_epoch(epoch => $milliseconds / 1000);
110 15 100       4632 if (defined $direction) {
111 10         43 my $minutes = ($direction."1") * ($mi + $hh * 60);
112 10         36 $dt->add(minutes => $minutes);
113             }
114 15         4907 return $dt;
115             }
116              
117             =head2 format_datetime
118              
119             Returns a JSON formatted date string for the passed DateTime object
120              
121             my $dt = DateTime->now;
122             my $formatter = DateTime::Format::JSON::MicrosoftDateFormat->new;
123             print $formatter->format_datetime($dt), "\n";
124              
125             However, format_datetime is typically used like this...
126              
127             use DateTime;
128             use DateTime::Format::JSON::MicrosoftDateFormat;
129             my $formatter = DateTime::Format::JSON::MicrosoftDateFormat->new;
130              
131             my $dt = DateTime->now;
132             $dt->set_formatter($formatter);
133             print "$dt\n"; #prints /Date(1392747078000)/
134              
135             Note: The format_datetime method returns all dates as UTC and does does not support time zone offset in output as it is not well supported in the Microsoft stack e.g. /Date(1392747078000-0500)/
136              
137             =cut
138              
139             sub format_datetime {
140 5     5 1 23817 my $self = shift;
141 5         11 my $dt = shift;
142 5         23 return sprintf("/Date(%s)/", $dt->epoch * 1000 + $dt->millisecond);
143             }
144              
145             =head1 BUGS
146              
147             Please log on RT and send an email to the author.
148              
149             =head1 SUPPORT
150              
151             DavisNetworks.com supports all Perl applications including this package.
152              
153             =head1 AUTHOR
154              
155             Michael R. Davis
156             CPAN ID: MRDVT
157             Satellite Tracking of People, LLC
158             mdavis@stopllc.com
159             http://www.stopllc.com/
160              
161             =head1 COPYRIGHT
162              
163             This program is free software licensed under the...
164              
165             The General Public License (GPL)
166             Version 2, June 1991
167              
168             The full text of the license can be found in the LICENSE file included with this module.
169              
170             =head1 SEE ALSO
171              
172             L<DateTime>
173              
174             =cut
175              
176             1;