001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import java.text.ParseException;
004import java.text.SimpleDateFormat;
005import java.util.Date;
006import java.util.Locale;
007import java.util.SimpleTimeZone;
008
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Choice;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1GeneralizedTime;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
013import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
014import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1UTCTime;
015import org.apache.commons.ssl.org.bouncycastle.asn1.DERGeneralizedTime;
016import org.apache.commons.ssl.org.bouncycastle.asn1.DERUTCTime;
017
018public class Time
019    extends ASN1Object
020    implements ASN1Choice
021{
022    ASN1Primitive time;
023
024    public static Time getInstance(
025        ASN1TaggedObject obj,
026        boolean          explicit)
027    {
028        return getInstance(obj.getObject()); // must be explicitly tagged
029    }
030
031    public Time(
032        ASN1Primitive   time)
033    {
034        if (!(time instanceof ASN1UTCTime)
035            && !(time instanceof ASN1GeneralizedTime))
036        {
037            throw new IllegalArgumentException("unknown object passed to Time");
038        }
039
040        this.time = time; 
041    }
042
043    /**
044     * Creates a time object from a given date - if the date is between 1950
045     * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
046     * is used.
047     *
048     * @param time a date object representing the time of interest.
049     */
050    public Time(
051        Date    time)
052    {
053        SimpleTimeZone      tz = new SimpleTimeZone(0, "Z");
054        SimpleDateFormat    dateF = new SimpleDateFormat("yyyyMMddHHmmss");
055
056        dateF.setTimeZone(tz);
057
058        String  d = dateF.format(time) + "Z";
059        int     year = Integer.parseInt(d.substring(0, 4));
060
061        if (year < 1950 || year > 2049)
062        {
063            this.time = new DERGeneralizedTime(d);
064        }
065        else
066        {
067            this.time = new DERUTCTime(d.substring(2));
068        }
069    }
070
071    /**
072     * Creates a time object from a given date and locale - if the date is between 1950
073     * and 2049 a UTCTime object is generated, otherwise a GeneralizedTime
074     * is used. You may need to use this constructor if the default locale
075     * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible with other ASN.1 implementations.
076     *
077     * @param time a date object representing the time of interest.
078     * @param locale an appropriate Locale for producing an ASN.1 GeneralizedTime value.
079     */
080    public Time(
081        Date    time,
082        Locale locale)
083    {
084        SimpleTimeZone      tz = new SimpleTimeZone(0, "Z");
085        SimpleDateFormat    dateF = new SimpleDateFormat("yyyyMMddHHmmss", locale);
086
087        dateF.setTimeZone(tz);
088
089        String  d = dateF.format(time) + "Z";
090        int     year = Integer.parseInt(d.substring(0, 4));
091
092        if (year < 1950 || year > 2049)
093        {
094            this.time = new DERGeneralizedTime(d);
095        }
096        else
097        {
098            this.time = new DERUTCTime(d.substring(2));
099        }
100    }
101
102    public static Time getInstance(
103        Object  obj)
104    {
105        if (obj == null || obj instanceof Time)
106        {
107            return (Time)obj;
108        }
109        else if (obj instanceof ASN1UTCTime)
110        {
111            return new Time((ASN1UTCTime)obj);
112        }
113        else if (obj instanceof ASN1GeneralizedTime)
114        {
115            return new Time((ASN1GeneralizedTime)obj);
116        }
117
118        throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
119    }
120
121    public String getTime()
122    {
123        if (time instanceof ASN1UTCTime)
124        {
125            return ((ASN1UTCTime)time).getAdjustedTime();
126        }
127        else
128        {
129            return ((ASN1GeneralizedTime)time).getTime();
130        }
131    }
132
133    public Date getDate()
134    {
135        try
136        {
137            if (time instanceof ASN1UTCTime)
138            {
139                return ((ASN1UTCTime)time).getAdjustedDate();
140            }
141            else
142            {
143                return ((ASN1GeneralizedTime)time).getDate();
144            }
145        }
146        catch (ParseException e)
147        {         // this should never happen
148            throw new IllegalStateException("invalid date string: " + e.getMessage());
149        }
150    }
151
152    /**
153     * Produce an object suitable for an ASN1OutputStream.
154     * <pre>
155     * Time ::= CHOICE {
156     *             utcTime        UTCTime,
157     *             generalTime    GeneralizedTime }
158     * </pre>
159     */
160    public ASN1Primitive toASN1Primitive()
161    {
162        return time;
163    }
164
165    public String toString()
166    {
167        return getTime();
168    }
169}