public static TimezoneMap fromConsensusTimezoneMap(
      final TreeMap<String, TimeZone> consensusTimezoneMap) {
    TimezoneMap timezoneMap = new TimezoneMap();
    Long holdStartMillis = null;
    DateTimeZone holdDateTimezone = null;
    Long lastEndMillis = null;

    for (String date : consensusTimezoneMap.keySet()) {
      final TimeZone timeZone = consensusTimezoneMap.get(date);
      final DateTimeZone dateTimeZone = DateTimeZone.forTimeZone(timeZone);
      final DateTime thisStartDateTime =
          TimeUtils.dateFormatter.withZone(dateTimeZone).parseDateTime(date);
      final long thisStartMillis = thisStartDateTime.getMillis();

      // Check if we need to flush a prior segment
      if (holdStartMillis != null && holdDateTimezone != dateTimeZone) {
        // Yes, this differs, end the previous segment with holdStartMillis as its
        // start time and thisStartMillis-1 as its end time
        timezoneMap.add(holdStartMillis, thisStartMillis - 1, holdDateTimezone);
        // Update holdStartMillis and holdDateTimezone for next time to be the start of this segment
        holdStartMillis = thisStartMillis;
        holdDateTimezone = dateTimeZone;
      } else if (holdStartMillis == null) {
        // This is the first time through, hold onto holdStartMillis and holdDateTimezone
        // for next time to be the start of the first  segment
        holdStartMillis = thisStartMillis;
        holdDateTimezone = dateTimeZone;
      } else {
        // Continue with the earlier timezone, no need to change anything
      }
      // Update lastEndMillis for closing up on the last segment
      lastEndMillis = thisStartMillis + DateTimeConstants.MILLIS_PER_DAY;
    }
    // Flush the last segment (unless it's empty)
    if (holdDateTimezone != null) {
      timezoneMap.add(holdStartMillis, lastEndMillis, holdDateTimezone);
    }
    return timezoneMap;
  }
  public static void main(final String[] args) {
    // Create test table
    TimezoneMap tzMap = new TimezoneMap();

    // Create sample tzMap based on Anne's BodyMedia map:
    // [ { "endDate" : "20110822T220048-0400", "startDate" : "20101221T000000-0500", "value" :
    // "US/Eastern"},
    //   { "endDate" : "20110921T192919-0700", "startDate" : "20110822T190048-0700", "value" :
    // "US/Pacific"},
    //   { "startDate" : "20110921T222919-0400","value" : "US/Eastern"
    //   } ]
    // Then extended to have a segment in Central time starting Wed, 22 May 2013 13:45:56 GMT and
    // ending
    // Sat, 01 Jun 2013 00:00:00 GMT
    tzMap.add(1292907600000L, 1314064848000L, DateTimeZone.forID("America/New_York"));
    tzMap.add(1314064848000L, 1316658559000L, DateTimeZone.forID("America/Los_Angeles"));
    tzMap.add(1316658559000L, 1369230356963L, DateTimeZone.forID("America/New_York"));
    tzMap.add(1369230356963L, 1370044800000L, DateTimeZone.forID("US/Central"));

    // This should be Eastern
    LocalDate d1 = new LocalDate(2011, 6, 15);
    tzMap.getStartOfDate(d1);

    // This should be Eastern
    LocalDate d2 = new LocalDate(2011, 8, 22);
    tzMap.getStartOfDate(d2);

    // This should be Pacific
    LocalDate d3 = new LocalDate(2011, 8, 23);
    tzMap.getStartOfDate(d3);

    // This should be Eastern
    LocalDate d3b = new LocalDate(2013, 5, 22);
    tzMap.getStartOfDate(d3b);

    // This should be Central
    LocalDate d3c = new LocalDate(2013, 5, 23);
    tzMap.getStartOfDate(d3c);

    // Get from before the start of the map.  This should default to using the first item in the map
    // and return
    // in America/New_York
    LocalDate d4 = new LocalDate(2010, 12, 21);
    tzMap.getStartOfDate(d4);

    LocalDate d5 = new LocalDate(2010, 1, 1);
    tzMap.getStartOfDate(d5);

    // Get from past the end of the map.  This should be Central
    LocalDate d6 = new LocalDate(2013, 6, 2);
    tzMap.getStartOfDate(d6);

    LocalDate d7 = new LocalDate(2013, 8, 2);
    tzMap.getStartOfDate(d7);

    // Try out fromConsensusTimezoneMap
    TreeMap<String, TimeZone> ctm1 = new TreeMap<String, TimeZone>();

    ctm1.put("2011-06-05", TimeZone.getTimeZone("America/New_York"));
    TimezoneMap tzm1 = fromConsensusTimezoneMap(ctm1);
    int tzm1S = tzm1.spans.size(); // should be 1 covering 6/15/11

    ctm1.put("2012-06-05", TimeZone.getTimeZone("America/New_York"));
    TimezoneMap tzm2 = fromConsensusTimezoneMap(ctm1);
    int tzm2S = tzm2.spans.size(); // should be 1 covering 6/15/11 - 6/15/12

    ctm1.put("2011-12-05", TimeZone.getTimeZone("US/Central"));
    TimezoneMap tzm3 = fromConsensusTimezoneMap(ctm1);
    int tzm3S =
        tzm3.spans
            .size(); // should be 3 covering 6/15/11 - 2011-12-04, 2011-12-05 - 6/14/12, and 6/15/12
  }