1 | /* | |
2 | * $Id: PdfDate.java 3117 2008-01-31 05:53:22Z xlv $ | |
3 | * | |
4 | * Copyright 1999, 2000, 2001, 2002 Bruno Lowagie | |
5 | * | |
6 | * The contents of this file are subject to the Mozilla Public License Version 1.1 | |
7 | * (the "License"); you may not use this file except in compliance with the License. | |
8 | * You may obtain a copy of the License at http://www.mozilla.org/MPL/ | |
9 | * | |
10 | * Software distributed under the License is distributed on an "AS IS" basis, | |
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
12 | * for the specific language governing rights and limitations under the License. | |
13 | * | |
14 | * The Original Code is 'iText, a free JAVA-PDF library'. | |
15 | * | |
16 | * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by | |
17 | * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. | |
18 | * All Rights Reserved. | |
19 | * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer | |
20 | * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. | |
21 | * | |
22 | * Contributor(s): all the names of the contributors are added in the source code | |
23 | * where applicable. | |
24 | * | |
25 | * Alternatively, the contents of this file may be used under the terms of the | |
26 | * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the | |
27 | * provisions of LGPL are applicable instead of those above. If you wish to | |
28 | * allow use of your version of this file only under the terms of the LGPL | |
29 | * License and not to allow others to use your version of this file under | |
30 | * the MPL, indicate your decision by deleting the provisions above and | |
31 | * replace them with the notice and other provisions required by the LGPL. | |
32 | * If you do not delete the provisions above, a recipient may use your version | |
33 | * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. | |
34 | * | |
35 | * This library is free software; you can redistribute it and/or modify it | |
36 | * under the terms of the MPL as stated above or under the terms of the GNU | |
37 | * Library General Public License as published by the Free Software Foundation; | |
38 | * either version 2 of the License, or any later version. | |
39 | * | |
40 | * This library is distributed in the hope that it will be useful, but WITHOUT | |
41 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
42 | * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more | |
43 | * details. | |
44 | * | |
45 | * If you didn't download this code from the following link, you should check if | |
46 | * you aren't using an obsolete version: | |
47 | * http://www.lowagie.com/iText/ | |
48 | */ | |
49 | ||
50 | package com.lowagie.text.pdf; | |
51 | ||
52 | import java.util.Calendar; | |
53 | import java.util.GregorianCalendar; | |
54 | import java.util.SimpleTimeZone; | |
55 | ||
56 | /** | |
57 | * <CODE>PdfDate</CODE> is the PDF date object. | |
58 | * <P> | |
59 | * PDF defines a standard date format. The PDF date format closely follows the format | |
60 | * defined by the international standard ASN.1 (Abstract Syntax Notation One, defined | |
61 | * in CCITT X.208 or ISO/IEC 8824). A date is a <CODE>PdfString</CODE> of the form: | |
62 | * <P><BLOCKQUOTE> | |
63 | * (D:YYYYMMDDHHmmSSOHH'mm') | |
64 | * </BLOCKQUOTE><P> | |
65 | * This object is described in the 'Portable Document Format Reference Manual version 1.3' | |
66 | * section 7.2 (page 183-184) | |
67 | * | |
68 | * @see PdfString | |
69 | * @see java.util.GregorianCalendar | |
70 | */ | |
71 | ||
72 | public class PdfDate extends PdfString { | |
73 | ||
74 | private static final int[] DATE_SPACE = {Calendar.YEAR, 4, 0, Calendar.MONTH, 2, -1, Calendar.DAY_OF_MONTH, 2, 0, | |
75 | Calendar.HOUR_OF_DAY, 2, 0, Calendar.MINUTE, 2, 0, Calendar.SECOND, 2, 0}; | |
76 | | |
77 | // constructors | |
78 | | |
79 | /** | |
80 | * Constructs a <CODE>PdfDate</CODE>-object. | |
81 | * | |
82 | * @param d the date that has to be turned into a <CODE>PdfDate</CODE>-object | |
83 | */ | |
84 | | |
85 | public PdfDate(Calendar d) { | |
86 | super(); | |
87 | StringBuilder date = new StringBuilder("D:"); | |
88 | date.append(setLength(d.get(Calendar.YEAR), 4)); | |
89 |
1
1. |
date.append(setLength(d.get(Calendar.MONTH) + 1, 2)); |
90 | date.append(setLength(d.get(Calendar.DATE), 2)); | |
91 | date.append(setLength(d.get(Calendar.HOUR_OF_DAY), 2)); | |
92 | date.append(setLength(d.get(Calendar.MINUTE), 2)); | |
93 | date.append(setLength(d.get(Calendar.SECOND), 2)); | |
94 |
2
1. 2. |
int timezone = (d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 60 * 1000); |
95 |
1
1. |
if (timezone == 0) { |
96 | date.append('Z'); | |
97 | } | |
98 |
2
1. 2. |
else if (timezone < 0) { |
99 | date.append('-'); | |
100 |
1
1. |
timezone = -timezone; |
101 | } | |
102 | else { | |
103 | date.append('+'); | |
104 | } | |
105 |
1
1. |
if (timezone != 0) { |
106 | date.append(setLength(timezone, 2)).append('\''); | |
107 |
4
1. 2. 3. 4. |
int zone = Math.abs((d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 1000)) - (timezone * 60); |
108 | date.append(setLength(zone, 2)).append('\''); | |
109 | } | |
110 | value = date.toString(); | |
111 | } | |
112 | | |
113 | /** | |
114 | * Constructs a <CODE>PdfDate</CODE>-object, representing the current day and time. | |
115 | */ | |
116 | | |
117 | public PdfDate() { | |
118 | this(new GregorianCalendar()); | |
119 | } | |
120 | | |
121 | /** | |
122 | * Adds a number of leading zeros to a given <CODE>String</CODE> in order to get a <CODE>String</CODE> | |
123 | * of a certain length. | |
124 | * | |
125 | * @param i a given number | |
126 | * @param length the length of the resulting <CODE>String</CODE> | |
127 | * @return the resulting <CODE>String</CODE> | |
128 | */ | |
129 | | |
130 | private String setLength(int i, int length) { // 1.3-1.4 problem fixed by Finn Bock | |
131 | StringBuilder tmp = new StringBuilder(); | |
132 | tmp.append(i); | |
133 |
2
1. setLength : changed conditional boundary → NO_COVERAGE 2. setLength : negated conditional → NO_COVERAGE |
while (tmp.length() < length) { |
134 | tmp.insert(0, "0"); | |
135 | } | |
136 |
1
1. setLength : removed call to java/lang/StringBuilder::setLength → NO_COVERAGE |
tmp.setLength(length); |
137 |
1
1. setLength : mutated return of Object value for com/lowagie/text/pdf/PdfDate::setLength to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return tmp.toString(); |
138 | } | |
139 | | |
140 | /** | |
141 | * Gives the W3C format of the PdfDate. | |
142 | * @return a formatted date | |
143 | */ | |
144 | public String getW3CDate() { | |
145 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return getW3CDate(value); |
146 | } | |
147 | | |
148 | /** | |
149 | * Gives the W3C format of the PdfDate. | |
150 | * @param d the date in the format D:YYYYMMDDHHmmSSOHH'mm' | |
151 | * @return a formatted date | |
152 | */ | |
153 | public static String getW3CDate(String d) { | |
154 |
1
1. getW3CDate : negated conditional → NO_COVERAGE |
if (d.startsWith("D:")) |
155 | d = d.substring(2); | |
156 | StringBuilder sb = new StringBuilder(); | |
157 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 4) |
158 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return "0000"; |
159 | sb.append(d, 0, 4); //year | |
160 | d = d.substring(4); | |
161 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 2) |
162 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
163 | sb.append('-').append(d, 0, 2); //month | |
164 | d = d.substring(2); | |
165 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 2) |
166 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
167 | sb.append('-').append(d, 0, 2); //day | |
168 | d = d.substring(2); | |
169 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 2) |
170 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
171 | sb.append('T').append(d, 0, 2); //hour | |
172 | d = d.substring(2); | |
173 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 2) { |
174 | sb.append(":00Z"); | |
175 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
176 | } | |
177 | sb.append(':').append(d, 0, 2); //minute | |
178 | d = d.substring(2); | |
179 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() < 2) { |
180 | sb.append('Z'); | |
181 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
182 | } | |
183 | sb.append(':').append(d, 0, 2); //second | |
184 | d = d.substring(2); | |
185 |
2
1. getW3CDate : negated conditional → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.startsWith("-") || d.startsWith("+")) { |
186 | String sign = d.substring(0, 1); | |
187 | d = d.substring(1); | |
188 | String h = "00"; | |
189 | String m = "00"; | |
190 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() >= 2) { |
191 | h = d.substring(0, 2); | |
192 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() > 2) { |
193 | d = d.substring(3); | |
194 |
2
1. getW3CDate : changed conditional boundary → NO_COVERAGE 2. getW3CDate : negated conditional → NO_COVERAGE |
if (d.length() >= 2) |
195 | m = d.substring(0, 2); | |
196 | } | |
197 | sb.append(sign).append(h).append(':').append(m); | |
198 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
199 | } | |
200 | } | |
201 | sb.append('Z'); | |
202 |
1
1. getW3CDate : mutated return of Object value for com/lowagie/text/pdf/PdfDate::getW3CDate to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return sb.toString(); |
203 | } | |
204 | | |
205 | /** | |
206 | * Converts a PDF string representing a date into a Calendar. | |
207 | * @param s the PDF string representing a date | |
208 | * @return a <CODE>Calendar</CODE> representing the date or <CODE>null</CODE> if the string | |
209 | * was not a date | |
210 | */ | |
211 | public static Calendar decode(String s) { | |
212 | try { | |
213 |
1
1. decode : negated conditional → NO_COVERAGE |
if (s.startsWith("D:")) |
214 | s = s.substring(2); | |
215 | GregorianCalendar calendar; | |
216 | int slen = s.length(); | |
217 | int idx = s.indexOf('Z'); | |
218 |
2
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : negated conditional → NO_COVERAGE |
if (idx >= 0) { |
219 | slen = idx; | |
220 | calendar = new GregorianCalendar(new SimpleTimeZone(0, "ZPDF")); | |
221 | } | |
222 | else { | |
223 | int sign = 1; | |
224 | idx = s.indexOf('+'); | |
225 |
2
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : negated conditional → NO_COVERAGE |
if (idx < 0) { |
226 | idx = s.indexOf('-'); | |
227 |
2
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : negated conditional → NO_COVERAGE |
if (idx >= 0) |
228 | sign = -1; | |
229 | } | |
230 |
2
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : negated conditional → NO_COVERAGE |
if (idx < 0) |
231 | calendar = new GregorianCalendar(); | |
232 | else { | |
233 |
3
1. decode : Replaced integer addition with subtraction → NO_COVERAGE 2. decode : Replaced integer addition with subtraction → NO_COVERAGE 3. decode : Replaced integer multiplication with division → NO_COVERAGE |
int offset = Integer.parseInt(s.substring(idx + 1, idx + 3)) * 60; |
234 |
3
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : Replaced integer addition with subtraction → NO_COVERAGE 3. decode : negated conditional → NO_COVERAGE |
if (idx + 5 < s.length()) |
235 |
3
1. decode : Replaced integer addition with subtraction → NO_COVERAGE 2. decode : Replaced integer addition with subtraction → NO_COVERAGE 3. decode : Replaced integer addition with subtraction → NO_COVERAGE |
offset += Integer.parseInt(s.substring(idx + 4, idx + 6)); |
236 |
2
1. decode : Replaced integer multiplication with division → NO_COVERAGE 2. decode : Replaced integer multiplication with division → NO_COVERAGE |
calendar = new GregorianCalendar(new SimpleTimeZone(offset * sign * 60000, "ZPDF")); |
237 | slen = idx; | |
238 | } | |
239 | } | |
240 |
1
1. decode : removed call to java/util/GregorianCalendar::clear → NO_COVERAGE |
calendar.clear(); |
241 | idx = 0; | |
242 |
3
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : Changed increment from 3 to -3 → NO_COVERAGE 3. decode : negated conditional → NO_COVERAGE |
for (int k = 0; k < DATE_SPACE.length; k += 3) { |
243 |
2
1. decode : changed conditional boundary → NO_COVERAGE 2. decode : negated conditional → NO_COVERAGE |
if (idx >= slen) |
244 | break; | |
245 |
5
1. decode : Replaced integer addition with subtraction → NO_COVERAGE 2. decode : Replaced integer addition with subtraction → NO_COVERAGE 3. decode : Replaced integer addition with subtraction → NO_COVERAGE 4. decode : Replaced integer addition with subtraction → NO_COVERAGE 5. decode : removed call to java/util/GregorianCalendar::set → NO_COVERAGE |
calendar.set(DATE_SPACE[k], Integer.parseInt(s.substring(idx, idx + DATE_SPACE[k + 1])) + DATE_SPACE[k + 2]); |
246 |
2
1. decode : Replaced integer addition with subtraction → NO_COVERAGE 2. decode : Replaced integer addition with subtraction → NO_COVERAGE |
idx += DATE_SPACE[k + 1]; |
247 | } | |
248 |
1
1. decode : mutated return of Object value for com/lowagie/text/pdf/PdfDate::decode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return calendar; |
249 | } | |
250 | catch (Exception e) { | |
251 |
1
1. decode : mutated return of Object value for com/lowagie/text/pdf/PdfDate::decode to ( if (x != null) null else throw new RuntimeException ) → NO_COVERAGE |
return null; |
252 | } | |
253 | } | |
254 | } | |
Mutations | ||
89 |
1.1 |
|
94 |
1.1 2.2 |
|
95 |
1.1 |
|
98 |
1.1 2.2 |
|
100 |
1.1 |
|
105 |
1.1 |
|
107 |
1.1 2.2 3.3 4.4 |
|
133 |
1.1 2.2 |
|
136 |
1.1 |
|
137 |
1.1 |
|
145 |
1.1 |
|
154 |
1.1 |
|
157 |
1.1 2.2 |
|
158 |
1.1 |
|
161 |
1.1 2.2 |
|
162 |
1.1 |
|
165 |
1.1 2.2 |
|
166 |
1.1 |
|
169 |
1.1 2.2 |
|
170 |
1.1 |
|
173 |
1.1 2.2 |
|
175 |
1.1 |
|
179 |
1.1 2.2 |
|
181 |
1.1 |
|
185 |
1.1 2.2 |
|
190 |
1.1 2.2 |
|
192 |
1.1 2.2 |
|
194 |
1.1 2.2 |
|
198 |
1.1 |
|
202 |
1.1 |
|
213 |
1.1 |
|
218 |
1.1 2.2 |
|
225 |
1.1 2.2 |
|
227 |
1.1 2.2 |
|
230 |
1.1 2.2 |
|
233 |
1.1 2.2 3.3 |
|
234 |
1.1 2.2 3.3 |
|
235 |
1.1 2.2 3.3 |
|
236 |
1.1 2.2 |
|
240 |
1.1 |
|
242 |
1.1 2.2 3.3 |
|
243 |
1.1 2.2 |
|
245 |
1.1 2.2 3.3 4.4 5.5 |
|
246 |
1.1 2.2 |
|
248 |
1.1 |
|
251 |
1.1 |