AcmeUtils { public static Instant parseTimestamp(String str) { Matcher m = DATE_PATTERN.matcher(str); if (!m.matches()) { throw new IllegalArgumentException("Illegal date: " + str); } int year = Integer.parseInt(m.group(1)); int month = Integer.parseInt(m.group(2)); int dom = Integer.parseInt(m.group(3)); int hour = Integer.parseInt(m.group(4)); int minute = Integer.parseInt(m.group(5)); int second = Integer.parseInt(m.group(6)); StringBuilder msStr = new StringBuilder(); if (m.group(7) != null) { msStr.append(m.group(7)); } while (msStr.length() < 3) { msStr.append('0'); } int ms = Integer.parseInt(msStr.toString()); String tz = m.group(8); if ("Z".equalsIgnoreCase(tz)) { tz = "GMT"; } else { tz = TZ_PATTERN.matcher(tz).replaceAll("GMT$1$2:$3"); } return ZonedDateTime.of( year, month, dom, hour, minute, second, ms * 1_000_000, ZoneId.of(tz)).toInstant(); } private  AcmeUtils(); static byte[] sha256hash(String z); static String hexEncode(byte[] data); static String base64UrlEncode(byte[] data); static byte[] base64UrlDecode(String base64); static boolean isValidBase64Url(@Nullable String base64); static String toAce(String domain); static Instant parseTimestamp(String str); @Nullable static String stripErrorPrefix(@Nullable String type); static void writeToPem(byte[] encoded, PemLabel label, Writer out); @Nullable static String getContentType(@Nullable String header); static void validateContact(URI contact);  }
@Test public void testParser() { assertThat(parseTimestamp("2015-12-27T22:58:35.006769519Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.00676951Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.0067695Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.006769Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.00676Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.0067Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.006Z"), isDate(2015, 12, 27, 22, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.01Z"), isDate(2015, 12, 27, 22, 58, 35, 10)); assertThat(parseTimestamp("2015-12-27T22:58:35.2Z"), isDate(2015, 12, 27, 22, 58, 35, 200)); assertThat(parseTimestamp("2015-12-27T22:58:35Z"), isDate(2015, 12, 27, 22, 58, 35)); assertThat(parseTimestamp("2015-12-27t22:58:35z"), isDate(2015, 12, 27, 22, 58, 35)); assertThat(parseTimestamp("2015-12-27T22:58:35.006769519+02:00"), isDate(2015, 12, 27, 20, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.006+02:00"), isDate(2015, 12, 27, 20, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35+02:00"), isDate(2015, 12, 27, 20, 58, 35)); assertThat(parseTimestamp("2015-12-27T21:58:35.006769519-02:00"), isDate(2015, 12, 27, 23, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T21:58:35.006-02:00"), isDate(2015, 12, 27, 23, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T21:58:35-02:00"), isDate(2015, 12, 27, 23, 58, 35)); assertThat(parseTimestamp("2015-12-27T22:58:35.006769519+0200"), isDate(2015, 12, 27, 20, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35.006+0200"), isDate(2015, 12, 27, 20, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T22:58:35+0200"), isDate(2015, 12, 27, 20, 58, 35)); assertThat(parseTimestamp("2015-12-27T21:58:35.006769519-0200"), isDate(2015, 12, 27, 23, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T21:58:35.006-0200"), isDate(2015, 12, 27, 23, 58, 35, 6)); assertThat(parseTimestamp("2015-12-27T21:58:35-0200"), isDate(2015, 12, 27, 23, 58, 35)); }
@Test public void testInvalid() { try { parseTimestamp(""); fail("accepted empty string"); } catch (IllegalArgumentException ex) { } try { parseTimestamp("abc"); fail("accepted nonsense string"); } catch (IllegalArgumentException ex) { } try { parseTimestamp("2015-12-27"); fail("accepted year only string"); } catch (IllegalArgumentException ex) { } try { parseTimestamp("2015-12-27T"); fail("accepted year only string"); } catch (IllegalArgumentException ex) { } }