*/
public static XMPDateTime parse(String iso8601String, XMPDateTime binValue) throws XMPException
{
if (iso8601String == null)
{
throw new XMPException("Parameter must not be null", XMPError.BADPARAM);
}
else if (iso8601String.length() == 0)
{
return binValue;
}
ParseState input = new ParseState(iso8601String);
int value;
if (input.ch(0) == '-')
{
input.skip();
}
// Extract the year.
value = input.gatherInt("Invalid year in date string", 9999);
if (input.hasNext() && input.ch() != '-')
{
throw new XMPException("Invalid date string, after year", XMPError.BADVALUE);
}
if (input.ch(0) == '-')
{
value = -value;
}
binValue.setYear(value);
if (!input.hasNext())
{
return binValue;
}
input.skip();
// Extract the month.
value = input.gatherInt("Invalid month in date string", 12);
if (input.hasNext() && input.ch() != '-')
{
throw new XMPException("Invalid date string, after month", XMPError.BADVALUE);
}
binValue.setMonth(value);
if (!input.hasNext())
{
return binValue;
}
input.skip();
// Extract the day.
value = input.gatherInt("Invalid day in date string", 31);
if (input.hasNext() && input.ch() != 'T')
{
throw new XMPException("Invalid date string, after day", XMPError.BADVALUE);
}
binValue.setDay(value);
if (!input.hasNext())
{
return binValue;
}
input.skip();
// Extract the hour.
value = input.gatherInt("Invalid hour in date string", 23);
binValue.setHour(value);
if (!input.hasNext())
{
return binValue;
}
// Extract the minute.
if (input.ch() == ':')
{
input.skip();
value = input.gatherInt("Invalid minute in date string", 59);
if (input.hasNext() &&
input.ch() != ':' && input.ch() != 'Z' && input.ch() != '+' && input.ch() != '-')
{
throw new XMPException("Invalid date string, after minute", XMPError.BADVALUE);
}
binValue.setMinute(value);
}
if (!input.hasNext())
{
return binValue;
}
else if (input.hasNext() && input.ch() == ':')
{
input.skip();
value = input.gatherInt("Invalid whole seconds in date string", 59);
if (input.hasNext() && input.ch() != '.' && input.ch() != 'Z' &&
input.ch() != '+' && input.ch() != '-')
{
throw new XMPException("Invalid date string, after whole seconds",
XMPError.BADVALUE);
}
binValue.setSecond(value);
if (input.ch() == '.')
{
input.skip();
int digits = input.pos();
value = input.gatherInt("Invalid fractional seconds in date string", 999999999);
if (input.hasNext() &&
(input.ch() != 'Z' && input.ch() != '+' && input.ch() != '-'))
{
throw new XMPException("Invalid date string, after fractional second",
XMPError.BADVALUE);
}
digits = input.pos() - digits;
for (; digits > 9; --digits)
{
value = value / 10;
}
for (; digits < 9; ++digits)
{
value = value * 10;
}
binValue.setNanoSecond(value);
}
}
else if (input.ch() != 'Z' && input.ch() != '+' && input.ch() != '-')
{
throw new XMPException("Invalid date string, after time", XMPError.BADVALUE);
}
int tzSign = 0;
int tzHour = 0;
int tzMinute = 0;
if (!input.hasNext())
{
// no Timezone at all
return binValue;
}
else if (input.ch() == 'Z')
{
input.skip();
}
else if (input.hasNext())
{
if (input.ch() == '+')
{
tzSign = 1;
}
else if (input.ch() == '-')
{
tzSign = -1;
}
else
{
throw new XMPException("Time zone must begin with 'Z', '+', or '-'",
XMPError.BADVALUE);
}
input.skip();
// Extract the time zone hour.
tzHour = input.gatherInt("Invalid time zone hour in date string", 23);
if (input.hasNext())
{
if (input.ch() == ':')
{
input.skip();
// Extract the time zone minute.
tzMinute = input.gatherInt("Invalid time zone minute in date string", 59);
}
else
{
throw new XMPException("Invalid date string, after time zone hour",
XMPError.BADVALUE);
}
}
}
// create a corresponding TZ and set it time zone
int offset = (tzHour * 3600 * 1000 + tzMinute * 60 * 1000) * tzSign;
binValue.setTimeZone(new SimpleTimeZone(offset, ""));
if (input.hasNext())
{
throw new XMPException(
"Invalid date string, extra chars at end", XMPError.BADVALUE);
}
return binValue;
}