Read a Time object from a Directions API result and convert it to a {@link ZonedDateTime}.

<p>We are expecting to receive something akin to the following:

<pre>
{
"text" : "4:27pm",
"time_zone" : "Australia/Sydney",
"value" : 1406528829
}
</pre>
541761
@Override
  public ZonedDateTime read(JsonReader reader) throws IOException {
    if (reader.peek() == JsonToken.NULL) {
      reader.nextNull();
      return null;
    }

    String timeZoneId = "";
    long secondsSinceEpoch = 0L;

    reader.beginObject();
    while (reader.hasNext()) {
      String name = reader.nextName();
      if (name.equals("text")) {
        // Ignore the human-readable rendering.
        reader.nextString();
      } else if (name.equals("time_zone")) {
        timeZoneId = reader.nextString();
      } else if (name.equals("value")) {
        secondsSinceEpoch = reader.nextLong();
      }
    }
    reader.endObject();

    return ZonedDateTime.ofInstant(
        Instant.ofEpochMilli(secondsSinceEpoch * 1000), ZoneId.of(timeZoneId));
  }
78104
@Deprecated
    @Override
    public TimeUnitAmount parseObject(String source, ParsePosition pos) {
        if (!isReady) {
            setup();
        }
        Number resultNumber = null;
        TimeUnit resultTimeUnit = null;
        int oldPos = pos.getIndex();
        int newPos = -1;
        int longestParseDistance = 0;
        String countOfLongestMatch = null;
        // we don't worry too much about speed on parsing, but this can be optimized later if needed.
        // Parse by iterating through all available patterns
        // and looking for the longest match.
        for (TimeUnit timeUnit : timeUnitToCountToPatterns.keySet()) {
            Map<String, Object[]> countToPattern = timeUnitToCountToPatterns.get(timeUnit);
            for (Entry<String, Object[]> patternEntry : countToPattern.entrySet()) {
                String count = patternEntry.getKey();
                for (int styl = FULL_NAME; styl < TOTAL_STYLES; ++styl) {
                    MessageFormat pattern = (MessageFormat) (patternEntry.getValue())[styl];
                    pos.setErrorIndex(-1);
                    pos.setIndex(oldPos);
                    // see if we can parse
                    Object parsed = pattern.parseObject(source, pos);
                    if (pos.getErrorIndex() != -1 || pos.getIndex() == oldPos) {
                        // nothing parsed
                        continue;
                    }
                    Number temp = null;
                    if (((Object[]) parsed).length != 0) {
                        // pattern with Number as beginning,
                        // such as "{0} d".
                        // check to make sure that the timeUnit is consistent
                        Object tempObj = ((Object[]) parsed)[0];
                        if (tempObj instanceof Number) {
                            temp = (Number) tempObj;
                        } else {
                            // Since we now format the number ourselves, parseObject will likely give us back a String
                            // for
                            // the number. When this happens we must parse the formatted number ourselves.
                            try {
                                temp = format.parse(tempObj.toString());
                            } catch (ParseException e) {
                                continue;
                            }
                        }
                    }
                    int parseDistance = pos.getIndex() - oldPos;
                    if (parseDistance > longestParseDistance) {
                        resultNumber = temp;
                        resultTimeUnit = timeUnit;
                        newPos = pos.getIndex();
                        longestParseDistance = parseDistance;
                        countOfLongestMatch = count;
                    }
                }
            }
        }
        /*
         * After find the longest match, parse the number. Result number could be null for the pattern without number
         * pattern. such as unit pattern in Arabic. When result number is null, use plural rule to set the number.
         */
        if (resultNumber == null && longestParseDistance != 0) {
            // set the number using plurrual count
            if (countOfLongestMatch.equals("zero")) {
                resultNumber = Integer.valueOf(0);
            } else if (countOfLongestMatch.equals("one")) {
                resultNumber = Integer.valueOf(1);
            } else if (countOfLongestMatch.equals("two")) {
                resultNumber = Integer.valueOf(2);
            } else {
                // should not happen.
                // TODO: how to handle?
                resultNumber = Integer.valueOf(3);
            }
        }
        if (longestParseDistance == 0) {
            pos.setIndex(oldPos);
            pos.setErrorIndex(0);
            return null;
        } else {
            pos.setIndex(newPos);
            pos.setErrorIndex(-1);
            return new TimeUnitAmount(resultNumber, resultTimeUnit);
        }
    }
160484
private static ZonedDateTime toZonedDateTimeUtc(final long epochValue, final EpochUnits units) {
        Preconditions.checkArgument(units != null, "units must be non-null");
        final Instant instant = units.toInstant(epochValue);
        return ZonedDateTime.ofInstant(instant, ZoneOffset.UTC);
    }
641392
def _time_to_datetime(value):
  
  if not isinstance(value, datetime.time):
    raise TypeError('Cannot convert to datetime expected time value; '
                    'received %s' % value)
  return datetime.datetime(1970, 1, 1,
                           value.hour, value.minute, value.second,
                           value.microsecond)
156032
static public String getFormattedDateTime(long dt, TimeZone tz, String format)
    {
        SimpleDateFormat df = new SimpleDateFormat(format);
        if(tz != null)
            df.setTimeZone(tz);
        return df.format(new Date(dt));
    }
129374
public java.util.TimeZone toTimeZone() {
        String id = getID();
        if (id.length() == 6 && (id.startsWith("+") || id.startsWith("-"))) {
            // standard format offset [+-]hh:mm
            // our ID is without any prefix, so we need to add the GMT back
            return java.util.TimeZone.getTimeZone("GMT" + getID());
        }
        // unusual offset, so setup a SimpleTimeZone as best we can
        return new java.util.SimpleTimeZone(iWallOffset, getID());
    }
1244835
function convertTime(value, fromUnit, toUnit)
{
    if(fromUnit != toUnit && value !== 0)
    {
        return value * (toUnit == 's'? 0.001 : 1000);
    }
    return value;
}
677236
private static String getTimeForApi (Date dt) {
        Calendar calendar = new GregorianCalendar();
        TimeZone timeZone = calendar.getTimeZone();
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(dt);
        return String.format("%tFT%<tRZ", cal);
    }
676407
private void readObject(ObjectInputStream stream)
                         throws IOException, ClassNotFoundException {
        stream.defaultReadObject();

        try {
            compiledPattern = compile(pattern);
        } catch (Exception e) {
            throw new InvalidObjectException("invalid pattern");
        }

        if (serialVersionOnStream < 1) {
            // didn't have defaultCenturyStart field
            initializeDefaultCentury();
        }
        else {
            // fill in dependent transient field
            parseAmbiguousDatesAsAfter(defaultCenturyStart);
        }
        serialVersionOnStream = currentSerialVersion;

        // If the deserialized object has a SimpleTimeZone, try
        // to replace it with a ZoneInfo equivalent in order to
        // be compatible with the SimpleTimeZone-based
        // implementation as much as possible.
        TimeZone tz = getTimeZone();
        if (tz instanceof SimpleTimeZone) {
            String id = tz.getID();
            TimeZone zi = TimeZone.getTimeZone(id);
            if (zi != null && zi.hasSameRules(tz) && zi.getID().equals(id)) {
                setTimeZone(zi);
            }
        }
    }
552043
private ZonedDateTime getDate(Element td) {
        //date
        Element date = td.select("span.sub_line").first();

        return ParserUtils.getDateFromStringToZoneId(date.html(), ZONE_ID, DateTimeFormatter.ofPattern("MMM / dd / yyyy", Locale.US));
    }
557687
static ZonedDateTime getDateFromStringToZoneId(String date, ZoneId zoneId, DateTimeFormatter formatter) throws DateTimeParseException {
        try {
            //noticed that date not parsed with non-US locale. For me this fix is helpful
            LocalDate localDate = LocalDate.parse(date, formatter);
            ZonedDateTime usDate = localDate.atStartOfDay(zoneId);
            return usDate.withZoneSameInstant(zoneId);
        } catch (Exception e) {
            //In case the parsing fail, we try without time
            try {
                ZonedDateTime usDate = LocalDate.parse(date, formatter).atStartOfDay(ZoneId.of(Constants.SHERDOG_TIME_ZONE));
                return usDate.withZoneSameInstant(zoneId);
            } catch (DateTimeParseException e2) {
                return null;
            }
        }
    }
208973
private static DateTime readOffset(boolean isPlus, TimeZone timeZone, DateTime dt, int years, int months, int days, int hours, int minutes, int seconds, int milliSeconds,
	    DateString ds, boolean checkAfterLast, DateTime defaultValue) {
	// timeZone=ThreadLocalPageContext.getTimeZone(timeZone);
	if (timeZone == null) return defaultValue;
	// HOUR
	int hourLength = ds.getPos();
	int hour = ds.readDigits();
	hourLength = ds.getPos() - hourLength;
	if (hour == -1) return defaultValue;

	// MINUTE
	int minute = 0;
	if (!ds.isAfterLast()) {
	    if (!(ds.fwIfCurrent(':') || ds.fwIfCurrent('.'))) return defaultValue;
	    minute = ds.readDigits();
	    if (minute == -1) return defaultValue;

	}
	else if (hourLength > 2) {
	    int h = hour / 100;
	    minute = hour - (h * 100);
	    hour = h;
	}

	if (minute > 59) return defaultValue;
	if (hour > 14 || (hour == 14 && minute > 0)) return defaultValue;

	long offset = hour * 60L * 60L * 1000L;
	offset += minute * 60 * 1000;

	if (!checkAfterLast || ds.isAfterLast()) {
	    long time = util.toTime(TimeZoneConstants.UTC, years, months, days, hours, minutes, seconds, milliSeconds, 0);

	    if (isPlus) time -= offset;
	    else time += offset;
	    return new DateTimeImpl(time, false);
	}
	return defaultValue;
    }
776326
private DateTime zonedDateTimeToJodaTime(final ChronoZonedDateTime<?> date) {
        return date == null ? null : new DateTime(date.toInstant().toEpochMilli(), DateTimeZone.UTC);
    }
142594
@Deprecated
    public static long parseTimeWithoutTimeZone(TimeZoneKey timeZoneKey, String value)
    {
        return TIME_FORMATTER.withZone(getDateTimeZone(timeZoneKey)).parseMillis(value);
    }
1098691
public static TimeZone toTimeZone(final ZoneOffset self) {
        if (ZoneOffset.UTC.equals(self)) {
            return TimeZone.getTimeZone("GMT");
        } else if (getSeconds(self) == 0) {
            return TimeZone.getTimeZone("GMT" + self.getId());
        } else {
            // TimeZone is only hours and minutes--no seconds
            ZoneOffset noSeconds = ZoneOffset.ofHoursMinutes(getHours(self), getMinutes(self));
            return TimeZone.getTimeZone("GMT" + noSeconds.getId());
        }
    }
1163318
public static Date convertTimeToDate(Date time)
    {
        if (time != null)
        {
            DataConverters.initGlobals();
            Calendar calendar = DataConverters.gCalendar;
            calendar.setTime(time);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            time = calendar.getTime();
        }       
        return time;
    }
560312
public static DateTimeZone readFrom(DataInput in, String id) throws IOException {
        switch (in.readUnsignedByte()) {
        case 'F':
            DateTimeZone fixed = new FixedDateTimeZone
                (id, in.readUTF(), (int)readMillis(in), (int)readMillis(in));
            if (fixed.equals(DateTimeZone.UTC)) {
                fixed = DateTimeZone.UTC;
            }
            return fixed;
        case 'C':
            return CachedDateTimeZone.forZone(PrecalculatedZone.readFrom(in, id));
        case 'P':
            return PrecalculatedZone.readFrom(in, id);
        default:
            throw new IOException("Invalid encoding");
        }
    }