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         StringBuffer date = new StringBuffer("D:");
88         date.append(setLength(d.get(Calendar.YEAR), 4));
89         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         int timezone = (d.get(Calendar.ZONE_OFFSET) + d.get(Calendar.DST_OFFSET)) / (60 * 60 * 1000);
95         if (timezone == 0) {
96             date.append('Z');
97         }
98         else if (timezone < 0) {
99             date.append('-');
100             timezone = -timezone;
101         }
102         else {
103             date.append('+');
104         }
105         if (timezone != 0) {
106             date.append(setLength(timezone, 2)).append('\'');
107             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         StringBuffer tmp = new StringBuffer();
132         tmp.append(i);
133         while (tmp.length() < length) {
134             tmp.insert(0, "0");
135         }
136         tmp.setLength(length);
137         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         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         if (d.startsWith("D:"))
155             d = d.substring(2);
156         StringBuffer sb = new StringBuffer();
157         if (d.length() < 4)
158             return "0000";
159         sb.append(d.substring(0, 4)); //year
160         d = d.substring(4);
161         if (d.length() < 2)
162             return sb.toString();
163         sb.append('-').append(d.substring(0, 2)); //month
164         d = d.substring(2);
165         if (d.length() < 2)
166             return sb.toString();
167         sb.append('-').append(d.substring(0, 2)); //day
168         d = d.substring(2);
169         if (d.length() < 2)
170             return sb.toString();
171         sb.append('T').append(d.substring(0, 2)); //hour
172         d = d.substring(2);
173         if (d.length() < 2) {
174             sb.append(":00Z");
175             return sb.toString();
176         }
177         sb.append(':').append(d.substring(0, 2)); //minute
178         d = d.substring(2);
179         if (d.length() < 2) {
180             sb.append('Z');
181             return sb.toString();
182         }
183         sb.append(':').append(d.substring(0, 2)); //second
184         d = d.substring(2);
185         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             if (d.length() >= 2) {
191                 h = d.substring(0, 2);
192                 if (d.length() > 2) {
193                     d = d.substring(3);
194                     if (d.length() >= 2)
195                         m = d.substring(0, 2);
196                 }
197                 sb.append(sign).append(h).append(':').append(m);
198                 return sb.toString();
199             }
200         }
201         sb.append('Z');
202         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             if (s.startsWith("D:"))
214                 s = s.substring(2);
215             GregorianCalendar calendar;
216             int slen = s.length();
217             int idx = s.indexOf('Z');
218             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                 if (idx < 0) {
226                     idx = s.indexOf('-');
227                     if (idx >= 0)
228                         sign = -1;
229                 }
230                 if (idx < 0)
231                     calendar = new GregorianCalendar();
232                 else {
233                     int offset = Integer.parseInt(s.substring(idx + 1, idx + 3)) * 60;
234                     if (idx + 5 < s.length())
235                         offset += Integer.parseInt(s.substring(idx + 4, idx + 6));
236                     calendar = new GregorianCalendar(new SimpleTimeZone(offset * sign * 60000, "ZPDF"));
237                     slen = idx;
238                 }
239             }
240             calendar.clear();
241             idx = 0;
242             for (int k = 0; k < DATE_SPACE.length; k += 3) {
243                 if (idx >= slen)
244                     break;
245                 calendar.set(DATE_SPACE[k], Integer.parseInt(s.substring(idx, idx + DATE_SPACE[k + 1])) + DATE_SPACE[k + 2]);
246                 idx += DATE_SPACE[k + 1];
247             }
248             return calendar;
249         }
250         catch (Exception e) {
251             return null;
252         }
253     }
254 }