1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.text.ParseException;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.text.SimpleDateFormat;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Date;
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.SimpleTimeZone;
8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport java.util.TimeZone;
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Generalized time object.
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class DERGeneralizedTime
14c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    extends ASN1Object
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    String      time;
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * return a generalized time from the passed in object
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception IllegalArgumentException if the object cannot be converted.
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static DERGeneralizedTime getInstance(
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Object  obj)
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (obj == null || obj instanceof DERGeneralizedTime)
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return (DERGeneralizedTime)obj;
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * return a Generalized Time object from a tagged object.
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param obj the tagged object holding the object we want
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param explicit true if the object is meant to be explicitly
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *              tagged false otherwise.
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @exception IllegalArgumentException if the tagged object cannot
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *               be converted.
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public static DERGeneralizedTime getInstance(
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        ASN1TaggedObject obj,
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean          explicit)
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        DERObject o = obj.getObject();
486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        if (explicit || o instanceof DERGeneralizedTime)
506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            return getInstance(o);
526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        else
546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            return new DERGeneralizedTime(((ASN1OctetString)o).getOctets());
566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
60c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * for local time, or Z+-HHMM on the end, for difference between local
62c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * time and UTC time. The fractional second amount f must consist of at
63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * least one number with trailing zeroes removed.
64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *
65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param time the time string.
66c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @exception IllegalArgumentException if String is an illegal format.
67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public DERGeneralizedTime(
69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        String  time)
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.time = time;
72c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        try
73c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            this.getDate();
75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
76c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        catch (ParseException e)
77c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
78c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            throw new IllegalArgumentException("invalid date string: " + e.getMessage());
79c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * base constructer from a java.util.date object
84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public DERGeneralizedTime(
86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Date time)
87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        dateF.setTimeZone(new SimpleTimeZone(0,"Z"));
91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.time = dateF.format(time);
93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    DERGeneralizedTime(
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  bytes)
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // explicitly convert to characters
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]  dateC = new char[bytes.length];
102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != dateC.length; i++)
104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            dateC[i] = (char)(bytes[i] & 0xff);
106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        this.time = new String(dateC);
109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
112c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * Return the time.
113c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     * @return The time string as it appeared in the encoded object.
114c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom     */
115c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public String getTimeString()
116c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
117c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return time;
118c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
119c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
120c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    /**
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * return the time - always in the form of
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *  YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * <p>
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * Normally in a certificate we would expect "Z" rather than "GMT",
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * however adding the "GMT" means we can just use:
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * <pre>
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * </pre>
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * To read in the time and get a date which is compatible with our local
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * time zone.
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public String getTime()
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        // standardise the format.
136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        //
137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (time.charAt(time.length() - 1) == 'Z')
138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return time.substring(0, time.length() - 1) + "GMT+00:00";
140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            int signPos = time.length() - 5;
144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            char sign = time.charAt(signPos);
145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            if (sign == '-' || sign == '+')
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                return time.substring(0, signPos)
148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    + "GMT"
149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    + time.substring(signPos, signPos + 3)
150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    + ":"
151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    + time.substring(signPos + 3);
152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            else
154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                signPos = time.length() - 3;
156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                sign = time.charAt(signPos);
157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                if (sign == '-' || sign == '+')
158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    return time.substring(0, signPos)
160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        + "GMT"
161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        + time.substring(signPos)
162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                        + ":00";
163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
166c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return time + calculateGMTOffset();
167c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
169c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private String calculateGMTOffset()
170c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
171c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        String sign = "+";
172c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        TimeZone timeZone = TimeZone.getDefault();
173c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int offset = timeZone.getRawOffset();
174c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (offset < 0)
175c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
176c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            sign = "-";
177c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            offset = -offset;
178c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int hours = offset / (60 * 60 * 1000);
180c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int minutes = (offset - (hours * 60 * 60 * 1000)) / (60 * 1000);
181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        try
183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (timeZone.useDaylightTime() && timeZone.inDaylightTime(this.getDate()))
185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                hours += sign.equals("+") ? 1 : -1;
187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        catch (ParseException e)
190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
191c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            // we'll do our best and ignore daylight savings
192c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
193c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
194c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return "GMT" + sign + convert(hours) + ":" + convert(minutes);
195c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
196c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
197c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private String convert(int time)
198c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
199c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (time < 10)
200c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
201c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            return "0" + time;
202c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
203c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
204c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return Integer.toString(time);
205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
207c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public Date getDate()
208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws ParseException
209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        SimpleDateFormat dateF;
211c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        String d = time;
212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
213c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (time.endsWith("Z"))
214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
215c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (hasFractionalSeconds())
216c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
217c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS'Z'");
218c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
219c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            else
220c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
221c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
222c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
223c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
224c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
225c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
226c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else if (time.indexOf('-') > 0 || time.indexOf('+') > 0)
227c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
228c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            d = this.getTime();
229c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (hasFractionalSeconds())
2306e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
231c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSSz");
232c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
233c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            else
234c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
236c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
237c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
238c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
242c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (hasFractionalSeconds())
243c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
244c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
245c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
246c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            else
247c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
248c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                dateF = new SimpleDateFormat("yyyyMMddHHmmss");
249c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
250c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
251c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
252c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
253c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
254c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (hasFractionalSeconds())
255c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
256c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            // java misinterprets extra digits as being milliseconds...
257c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            String frac = d.substring(14);
258c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            int    index;
259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            for (index = 1; index < frac.length(); index++)
260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
261c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                char ch = frac.charAt(index);
262c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                if (!('0' <= ch && ch <= '9'))
263c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
264c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    break;
265c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
266c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
2676e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
268c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (index - 1 > 3)
269c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
270c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                frac = frac.substring(0, 4) + frac.substring(index);
271c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                d = d.substring(0, 14) + frac;
272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
2736e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else if (index - 1 == 1)
2746e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
2756e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                frac = frac.substring(0, index) + "00" + frac.substring(index);
2766e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                d = d.substring(0, 14) + frac;
2776e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
2786e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            else if (index - 1 == 2)
2796e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
2806e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                frac = frac.substring(0, index) + "0" + frac.substring(index);
2816e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                d = d.substring(0, 14) + frac;
2826e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
284c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
285c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return dateF.parse(d);
286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
287c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
288c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    private boolean hasFractionalSeconds()
289c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
290c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return time.indexOf('.') == 14;
291c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
292c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private byte[] getOctets()
294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        char[]  cs = time.toCharArray();
296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  bs = new byte[cs.length];
297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        for (int i = 0; i != cs.length; i++)
299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
300b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            bs[i] = (byte)cs[i];
301b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
302b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
303b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return bs;
304b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
305b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
306b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
307b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    void encode(
308b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        DEROutputStream  out)
309b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
310b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
311b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        out.writeEncoded(GENERALIZED_TIME, this.getOctets());
312b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
313b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
314c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    boolean asn1Equals(
315c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        DERObject  o)
316b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
317c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (!(o instanceof DERGeneralizedTime))
318b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
319b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            return false;
320b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
321b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
322b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return time.equals(((DERGeneralizedTime)o).time);
323b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
324b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
325b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public int hashCode()
326b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
327b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        return time.hashCode();
328b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
329b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
330