public DateTime getStartOfDate(LocalDate date) {
    // Get the milisecond time for the start of that date in UTC
    long utcStartMillis = date.toDateTimeAtStartOfDay(DateTimeZone.UTC).getMillis();
    // Lookup the timezone for that time - 12 and +12 hours since timezones range from
    // UTC-12h to UTC+12h so the real start time will be within that range
    long minStartMillis = utcStartMillis - DateTimeConstants.MILLIS_PER_DAY / 2;
    long maxStartMillis = utcStartMillis + DateTimeConstants.MILLIS_PER_DAY / 2;

    TimespanSegment<DateTimeZone> minTimespan = this.queryPoint(minStartMillis);
    TimespanSegment<DateTimeZone> maxTimespan = this.queryPoint(maxStartMillis);
    DateTimeZone realTz = null;
    DateTime realDateStart = null;

    // Check if they agree
    if (minTimespan == maxTimespan) {
      // Ok, they agree so we're good, just use the consensus timezone
      realTz = minTimespan.getValue();
      realDateStart = date.toDateTimeAtStartOfDay(realTz);
    } else {
      // The start and end timespans are different, compute the start time in each and see which if
      // either intersect
      DateTime minTzStartDT = date.toDateTimeAtStartOfDay(minTimespan.getValue());
      DateTime maxTzStartDT = date.toDateTimeAtStartOfDay(maxTimespan.getValue());
      // Does the earlier one fall within the timespan for the minTimezone
      long minTzStartMillis = minTzStartDT.getMillis();
      long maxTzStartMillis = maxTzStartDT.getMillis();
      if (minTimespan.isTimeInSpan(minTzStartMillis)) {
        // First one works, keep it
        realTz = minTimespan.getValue();
        realDateStart = minTzStartDT;
      } else if (maxTimespan.isTimeInSpan(maxStartMillis)) {
        // Last one works, keep it
        realTz = maxTimespan.getValue();
        realDateStart = maxTzStartDT;
      } else {
        // Something weird is going on here, complain and return GMT
        System.out.println(
            "Cant figure out start of date "
                + date.toString()
                + ", "
                + minTimespan
                + " does not contain "
                + minTzStartDT
                + " and "
                + maxTimespan
                + " does not contain "
                + maxTzStartDT);
        return (date.toDateTimeAtStartOfDay(DateTimeZone.UTC));
      }
    }

    // System.out.println("Start of date "+date.toString()+", in "+realTz + ": " + realDateStart);
    return (realDateStart);
  }
 public DateTimeZone getMainTimezone() {
   Map<DateTimeZone, Long> timespentInTimezoneMap = new HashMap<DateTimeZone, Long>();
   for (TimespanSegment<DateTimeZone> span : spans) {
     long timeSpent = span.getEnd() - span.getStart();
     if (timespentInTimezoneMap.containsKey(span.getValue())) {
       final Long timeAlreadySpent = timespentInTimezoneMap.get(span.getValue());
       timespentInTimezoneMap.put(span.getValue(), timeAlreadySpent + timeSpent);
     } else {
       timespentInTimezoneMap.put(span.getValue(), timeSpent);
     }
   }
   long maxTimespent = Long.MIN_VALUE;
   DateTimeZone mainTimezone = null;
   for (DateTimeZone dateTimeZone : timespentInTimezoneMap.keySet()) {
     if (timespentInTimezoneMap.get(dateTimeZone) > maxTimespent) {
       maxTimespent = timespentInTimezoneMap.get(dateTimeZone);
       mainTimezone = dateTimeZone;
     }
   }
   return mainTimezone;
 }