package org.apache.commons.ssl.asn1; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.SimpleTimeZone; /** UTC time object. */ public class DERUTCTime extends ASN1Object { String time; /** * return an UTC Time from the passed in object. * * @throws IllegalArgumentException if the object cannot be converted. */ public static DERUTCTime getInstance( Object obj) { if (obj == null || obj instanceof DERUTCTime) { return (DERUTCTime) obj; } if (obj instanceof ASN1OctetString) { return new DERUTCTime(((ASN1OctetString) obj).getOctets()); } throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName()); } /** * return an UTC Time from a tagged object. * * @param obj the tagged object holding the object we want * @param explicit true if the object is meant to be explicitly * tagged false otherwise. * @throws IllegalArgumentException if the tagged object cannot * be converted. */ public static DERUTCTime getInstance( ASN1TaggedObject obj, boolean explicit) { return getInstance(obj.getObject()); } /** * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were * never encoded. When you're creating one of these objects from scratch, that's * what you want to use, otherwise we'll try to deal with whatever gets read from * the input stream... (this is why the input format is different from the getTime() * method output). *
* * @param time the time string. */ public DERUTCTime( String time) { this.time = time; try { this.getDate(); } catch (ParseException e) { throw new IllegalArgumentException("invalid date string: " + e.getMessage()); } } /** base constructer from a java.util.date object */ public DERUTCTime( Date time) { SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmss'Z'"); dateF.setTimeZone(new SimpleTimeZone(0, "Z")); this.time = dateF.format(time); } DERUTCTime( byte[] bytes) { // // explicitly convert to characters // char[] dateC = new char[bytes.length]; for (int i = 0; i != dateC.length; i++) { dateC[i] = (char) (bytes[i] & 0xff); } this.time = new String(dateC); } /** * return the time as a date based on whatever a 2 digit year will return. For * standardised processing use getAdjustedDate(). * * @return the resulting date * @throws ParseException if the date string cannot be parsed. */ public Date getDate() throws ParseException { SimpleDateFormat dateF = new SimpleDateFormat("yyMMddHHmmssz"); return dateF.parse(getTime()); } /** * return the time as an adjusted date * in the range of 1950 - 2049. * * @return a date in the range of 1950 to 2049. * @throws ParseException if the date string cannot be parsed. */ public Date getAdjustedDate() throws ParseException { SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); dateF.setTimeZone(new SimpleTimeZone(0, "Z")); return dateF.parse(getAdjustedTime()); } /** * return the time - always in the form of * YYMMDDhhmmssGMT(+hh:mm|-hh:mm). * * Normally in a certificate we would expect "Z" rather than "GMT", * however adding the "GMT" means we can just use: *
* dateF = new SimpleDateFormat("yyMMddHHmmssz");
*
* To read in the time and get a date which is compatible with our local
* time zone.
*
* Note: In some cases, due to the local date processing, this
* may lead to unexpected results. If you want to stick the normal
* convention of 1950 to 2049 use the getAdjustedTime() method.
*/
public String getTime() {
//
// standardise the format.
//
if (time.indexOf('-') < 0 && time.indexOf('+') < 0) {
if (time.length() == 11) {
return time.substring(0, 10) + "00GMT+00:00";
} else {
return time.substring(0, 12) + "GMT+00:00";
}
} else {
int index = time.indexOf('-');
if (index < 0) {
index = time.indexOf('+');
}
String d = time;
if (index == time.length() - 3) {
d += "00";
}
if (index == 10) {
return d.substring(0, 10) + "00GMT" + d.substring(10, 13) + ":" + d.substring(13, 15);
} else {
return d.substring(0, 12) + "GMT" + d.substring(12, 15) + ":" + d.substring(15, 17);
}
}
}
/**
* return a time string as an adjusted date with a 4 digit year. This goes
* in the range of 1950 - 2049.
*/
public String getAdjustedTime() {
String d = this.getTime();
if (d.charAt(0) < '5') {
return "20" + d;
} else {
return "19" + d;
}
}
private byte[] getOctets() {
char[] cs = time.toCharArray();
byte[] bs = new byte[cs.length];
for (int i = 0; i != cs.length; i++) {
bs[i] = (byte) cs[i];
}
return bs;
}
void encode(
DEROutputStream out)
throws IOException {
out.writeEncoded(UTC_TIME, this.getOctets());
}
boolean asn1Equals(
DERObject o) {
if (!(o instanceof DERUTCTime)) {
return false;
}
return time.equals(((DERUTCTime) o).time);
}
public int hashCode() {
return time.hashCode();
}
public String toString() {
return time;
}
}