Program: 24172
Project: 24172
Buggy source:
/** 
 * Formats a date or a time range according to the local conventions. <p> Example output strings (date formats in these examples are shown using the US date format convention but that may change depending on the local settings): <ul> <li>10:15am</li> <li>3:00pm - 4:00pm</li> <li>3pm - 4pm</li> <li>3PM - 4PM</li> <li>08:00 - 17:00</li> <li>Oct 9</li> <li>Tue, Oct 9</li> <li>October 9, 2007</li> <li>Oct 9 - 10</li> <li>Oct 9 - 10, 2007</li> <li>Oct 28 - Nov 3, 2007</li> <li>Dec 31, 2007 - Jan 1, 2008</li> <li>Oct 9, 8:00am - Oct 10, 5:00pm</li> <li>12/31/2007 - 01/01/2008</li> </ul> <p> The flags argument is a bitmask of options from the following list: <ul> <li>FORMAT_SHOW_TIME</li> <li>FORMAT_SHOW_WEEKDAY</li> <li>FORMAT_SHOW_YEAR</li> <li>FORMAT_NO_YEAR</li> <li>FORMAT_SHOW_DATE</li> <li>FORMAT_NO_MONTH_DAY</li> <li>FORMAT_12HOUR</li> <li>FORMAT_24HOUR</li> <li>FORMAT_CAP_AMPM</li> <li>FORMAT_NO_NOON</li> <li>FORMAT_CAP_NOON</li> <li>FORMAT_NO_MIDNIGHT</li> <li>FORMAT_CAP_MIDNIGHT</li> <li>FORMAT_UTC</li> <li>FORMAT_ABBREV_TIME</li> <li>FORMAT_ABBREV_WEEKDAY</li> <li>FORMAT_ABBREV_MONTH</li> <li>FORMAT_ABBREV_ALL</li> <li>FORMAT_NUMERIC_DATE</li> </ul> <p> If FORMAT_SHOW_TIME is set, the time is shown as part of the date range. If the start and end time are the same, then just the start time is shown. <p> If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown. <p> If FORMAT_SHOW_YEAR is set, then the year is always shown. If FORMAT_NO_YEAR is set, then the year is not shown. If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year is shown only if it is different from the current year, or if the start and end dates fall on different years.  If both are set, FORMAT_SHOW_YEAR takes precedence. <p> Normally the date is shown unless the start and end day are the same. If FORMAT_SHOW_DATE is set, then the date is always shown, even for same day ranges. <p> If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the month name will be shown, not the day of the month.  For example, "January, 2008" instead of "January 6 - 12, 2008". <p> If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM" and "PM" are capitalized. <p> If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is shown instead of "noon". <p> If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is shown instead of "noon". <p> If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is shown instead of "midnight". <p> If FORMAT_CAP_NOON is set and 12-hour time is used, then "Midnight" is shown instead of "midnight". <p> If FORMAT_12HOUR is set and the time is shown, then the time is shown in the 12-hour time format. You should not normally set this. Instead, let the time format be chosen automatically according to the system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then FORMAT_24HOUR takes precedence. <p> If FORMAT_24HOUR is set and the time is shown, then the time is shown in the 24-hour time format. You should not normally set this. Instead, let the time format be chosen automatically according to the system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then FORMAT_24HOUR takes precedence. <p> If FORMAT_UTC is set, then the UTC timezone is used for the start and end milliseconds. <p> If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the start and end times (if shown) are abbreviated by not showing the minutes if they are zero.  For example, instead of "3:00pm" the time would be abbreviated to "3pm". <p> If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is abbreviated to a 3-letter string. <p> If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated to a 3-letter string. <p> If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown) are abbreviated to 3-letter strings. <p> If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format instead of using the name of the month.  For example, "12/31/2008" instead of "December 31, 2008".
 * @param context the context is required only if the time is shown
 * @param startMillis the start time in UTC milliseconds
 * @param endMillis the end time in UTC milliseconds
 * @param flags a bit mask of options
 * @return a string containing the formatted date/time range.
 */
public static String formatDateRange(Context context,long startMillis,long endMillis,int flags){
  Resources res=Resources.getSystem();
  boolean showTime=(flags & FORMAT_SHOW_TIME) != 0;
  boolean showWeekDay=(flags & FORMAT_SHOW_WEEKDAY) != 0;
  boolean showYear=(flags & FORMAT_SHOW_YEAR) != 0;
  boolean noYear=(flags & FORMAT_NO_YEAR) != 0;
  boolean useUTC=(flags & FORMAT_UTC) != 0;
  boolean abbrevWeekDay=(flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
  boolean abbrevMonth=(flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
  boolean noMonthDay=(flags & FORMAT_NO_MONTH_DAY) != 0;
  boolean numericDate=(flags & FORMAT_NUMERIC_DATE) != 0;
  boolean isInstant=(startMillis == endMillis);
  Time startDate=useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
  startDate.set(startMillis);
  Time endDate;
  int dayDistance;
  if (isInstant) {
    endDate=startDate;
    dayDistance=0;
  }
 else {
    endDate=useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
    endDate.set(endMillis);
    int startJulianDay=Time.getJulianDay(startMillis,startDate.gmtoff);
    int endJulianDay=Time.getJulianDay(endMillis,endDate.gmtoff);
    dayDistance=endJulianDay - startJulianDay;
  }
  if (!isInstant && (endDate.hour | endDate.minute | endDate.second) == 0 && (!showTime || dayDistance <= 1)) {
    endDate.monthDay-=1;
    endDate.normalize(true);
  }
  int startDay=startDate.monthDay;
  int startMonthNum=startDate.month;
  int startYear=startDate.year;
  int endDay=endDate.monthDay;
  int endMonthNum=endDate.month;
  int endYear=endDate.year;
  String startWeekDayString="String_Node_Str";
  String endWeekDayString="String_Node_Str";
  if (showWeekDay) {
    String weekDayFormat="String_Node_Str";
    if (abbrevWeekDay) {
      weekDayFormat=ABBREV_WEEKDAY_FORMAT;
    }
 else {
      weekDayFormat=WEEKDAY_FORMAT;
    }
    startWeekDayString=startDate.format(weekDayFormat);
    endWeekDayString=isInstant ? startWeekDayString : endDate.format(weekDayFormat);
  }
  String startTimeString="String_Node_Str";
  String endTimeString="String_Node_Str";
  if (showTime) {
    String startTimeFormat="String_Node_Str";
    String endTimeFormat="String_Node_Str";
    boolean force24Hour=(flags & FORMAT_24HOUR) != 0;
    boolean force12Hour=(flags & FORMAT_12HOUR) != 0;
    boolean use24Hour;
    if (force24Hour) {
      use24Hour=true;
    }
 else     if (force12Hour) {
      use24Hour=false;
    }
 else {
      use24Hour=DateFormat.is24HourFormat(context);
    }
    if (use24Hour) {
      startTimeFormat=HOUR_MINUTE_24;
      endTimeFormat=HOUR_MINUTE_24;
    }
 else {
      boolean abbrevTime=(flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
      boolean capAMPM=(flags & FORMAT_CAP_AMPM) != 0;
      boolean noNoon=(flags & FORMAT_NO_NOON) != 0;
      boolean capNoon=(flags & FORMAT_CAP_NOON) != 0;
      boolean noMidnight=(flags & FORMAT_NO_MIDNIGHT) != 0;
      boolean capMidnight=(flags & FORMAT_CAP_MIDNIGHT) != 0;
      boolean startOnTheHour=startDate.minute == 0 && startDate.second == 0;
      boolean endOnTheHour=endDate.minute == 0 && endDate.second == 0;
      if (abbrevTime && startOnTheHour) {
        if (capAMPM) {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_cap_ampm);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_ampm);
        }
      }
 else {
        if (capAMPM) {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_minute_ampm);
        }
      }
      if (!isInstant) {
        if (abbrevTime && endOnTheHour) {
          if (capAMPM) {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_cap_ampm);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_ampm);
          }
        }
 else {
          if (capAMPM) {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_minute_ampm);
          }
        }
        if (endDate.hour == 12 && endOnTheHour && !noNoon) {
          if (capNoon) {
            endTimeFormat=res.getString(com.android.internal.R.string.Noon);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.noon);
          }
        }
 else         if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
          if (capMidnight) {
            endTimeFormat=res.getString(com.android.internal.R.string.Midnight);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.midnight);
          }
        }
      }
      if (startDate.hour == 12 && startOnTheHour && !noNoon) {
        if (capNoon) {
          startTimeFormat=res.getString(com.android.internal.R.string.Noon);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.noon);
        }
      }
    }
    startTimeString=startDate.format(startTimeFormat);
    endTimeString=isInstant ? startTimeString : endDate.format(endTimeFormat);
  }
  if (showYear) {
  }
 else   if (noYear) {
    showYear=false;
  }
 else   if (startYear != endYear) {
    showYear=true;
  }
 else {
    Time currentTime=new Time();
    currentTime.setToNow();
    showYear=startYear != currentTime.year;
  }
  String defaultDateFormat, fullFormat, dateRange;
  if (numericDate) {
    defaultDateFormat=res.getString(com.android.internal.R.string.numeric_date);
  }
 else   if (showYear) {
    if (abbrevMonth) {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_year);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_day_year);
      }
    }
 else {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_year);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_day_year);
      }
    }
  }
 else {
    if (abbrevMonth) {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_day);
      }
    }
 else {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.month);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_day);
      }
    }
  }
  if (showWeekDay) {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
    }
 else {
      fullFormat=res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
    }
  }
 else {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.date1_time1_date2_time2);
    }
 else {
      fullFormat=res.getString(com.android.internal.R.string.date1_date2);
    }
  }
  if (noMonthDay && startMonthNum == endMonthNum) {
    String startDateString=startDate.format(defaultDateFormat);
    return startDateString;
  }
  if (startYear != endYear || noMonthDay) {
    String startDateString=startDate.format(defaultDateFormat);
    String endDateString=endDate.format(defaultDateFormat);
    dateRange=String.format(fullFormat,startWeekDayString,startDateString,startTimeString,endWeekDayString,endDateString,endTimeString);
    return dateRange;
  }
  String monthFormat;
  if (numericDate) {
    monthFormat=NUMERIC_MONTH_FORMAT;
  }
 else   if (abbrevMonth) {
    monthFormat=ABBREV_MONTH_FORMAT;
  }
 else {
    monthFormat=MONTH_FORMAT;
  }
  String startMonthString=startDate.format(monthFormat);
  String startMonthDayString=startDate.format(MONTH_DAY_FORMAT);
  String startYearString=startDate.format(YEAR_FORMAT);
  String endMonthString=isInstant ? null : endDate.format(monthFormat);
  String endMonthDayString=isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
  String endYearString=isInstant ? null : endDate.format(YEAR_FORMAT);
  if (startMonthNum != endMonthNum) {
    int index=0;
    if (showWeekDay)     index=1;
    if (showYear)     index+=2;
    if (showTime)     index+=4;
    if (numericDate)     index+=8;
    int resId=sameYearTable[index];
    fullFormat=res.getString(resId);
    dateRange=String.format(fullFormat,startWeekDayString,startMonthString,startMonthDayString,startYearString,startTimeString,endWeekDayString,endMonthString,endMonthDayString,endYearString,endTimeString);
    return dateRange;
  }
  if (startDay != endDay) {
    int index=0;
    if (showWeekDay)     index=1;
    if (showYear)     index+=2;
    if (showTime)     index+=4;
    if (numericDate)     index+=8;
    int resId=sameMonthTable[index];
    fullFormat=res.getString(resId);
    dateRange=String.format(fullFormat,startWeekDayString,startMonthString,startMonthDayString,startYearString,startTimeString,endWeekDayString,endMonthString,endMonthDayString,endYearString,endTimeString);
    return dateRange;
  }
  boolean showDate=(flags & FORMAT_SHOW_DATE) != 0;
  if (!showTime && !showDate && !showWeekDay)   showDate=true;
  String timeString="String_Node_Str";
  if (showTime) {
    if (isInstant) {
      timeString=startTimeString;
    }
 else {
      String timeFormat=res.getString(com.android.internal.R.string.time1_time2);
      timeString=String.format(timeFormat,startTimeString,endTimeString);
    }
  }
  fullFormat="String_Node_Str";
  String dateString="String_Node_Str";
  if (showDate) {
    dateString=startDate.format(defaultDateFormat);
    if (showWeekDay) {
      if (showTime) {
        fullFormat=res.getString(com.android.internal.R.string.time_wday_date);
      }
 else {
        fullFormat=res.getString(com.android.internal.R.string.wday_date);
      }
    }
 else {
      if (showTime) {
        fullFormat=res.getString(com.android.internal.R.string.time_date);
      }
 else {
        return dateString;
      }
    }
  }
 else   if (showWeekDay) {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.time_wday);
    }
 else {
      return startWeekDayString;
    }
  }
 else   if (showTime) {
    return timeString;
  }
  dateRange=String.format(fullFormat,timeString,startWeekDayString,dateString);
  return dateRange;
}

Fixed version (ground truth):
/** 
 * Formats a date or a time range according to the local conventions. <p> Example output strings (date formats in these examples are shown using the US date format convention but that may change depending on the local settings): <ul> <li>10:15am</li> <li>3:00pm - 4:00pm</li> <li>3pm - 4pm</li> <li>3PM - 4PM</li> <li>08:00 - 17:00</li> <li>Oct 9</li> <li>Tue, Oct 9</li> <li>October 9, 2007</li> <li>Oct 9 - 10</li> <li>Oct 9 - 10, 2007</li> <li>Oct 28 - Nov 3, 2007</li> <li>Dec 31, 2007 - Jan 1, 2008</li> <li>Oct 9, 8:00am - Oct 10, 5:00pm</li> <li>12/31/2007 - 01/01/2008</li> </ul> <p> The flags argument is a bitmask of options from the following list: <ul> <li>FORMAT_SHOW_TIME</li> <li>FORMAT_SHOW_WEEKDAY</li> <li>FORMAT_SHOW_YEAR</li> <li>FORMAT_NO_YEAR</li> <li>FORMAT_SHOW_DATE</li> <li>FORMAT_NO_MONTH_DAY</li> <li>FORMAT_12HOUR</li> <li>FORMAT_24HOUR</li> <li>FORMAT_CAP_AMPM</li> <li>FORMAT_NO_NOON</li> <li>FORMAT_CAP_NOON</li> <li>FORMAT_NO_MIDNIGHT</li> <li>FORMAT_CAP_MIDNIGHT</li> <li>FORMAT_UTC</li> <li>FORMAT_ABBREV_TIME</li> <li>FORMAT_ABBREV_WEEKDAY</li> <li>FORMAT_ABBREV_MONTH</li> <li>FORMAT_ABBREV_ALL</li> <li>FORMAT_NUMERIC_DATE</li> </ul> <p> If FORMAT_SHOW_TIME is set, the time is shown as part of the date range. If the start and end time are the same, then just the start time is shown. <p> If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown. <p> If FORMAT_SHOW_YEAR is set, then the year is always shown. If FORMAT_NO_YEAR is set, then the year is not shown. If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year is shown only if it is different from the current year, or if the start and end dates fall on different years.  If both are set, FORMAT_SHOW_YEAR takes precedence. <p> Normally the date is shown unless the start and end day are the same. If FORMAT_SHOW_DATE is set, then the date is always shown, even for same day ranges. <p> If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the month name will be shown, not the day of the month.  For example, "January, 2008" instead of "January 6 - 12, 2008". <p> If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM" and "PM" are capitalized.  You should not use this flag because in some locales these terms cannot be capitalized, and in many others it doesn't make sense to do so even though it is possible. <p> If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is shown instead of "noon". <p> If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is shown instead of "noon".  You should probably not use this flag because in many locales it will not make sense to capitalize the term. <p> If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is shown instead of "midnight". <p> If FORMAT_CAP_MIDNIGHT is set and 12-hour time is used, then "Midnight" is shown instead of "midnight".  You should probably not use this flag because in many locales it will not make sense to capitalize the term. <p> If FORMAT_12HOUR is set and the time is shown, then the time is shown in the 12-hour time format. You should not normally set this. Instead, let the time format be chosen automatically according to the system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then FORMAT_24HOUR takes precedence. <p> If FORMAT_24HOUR is set and the time is shown, then the time is shown in the 24-hour time format. You should not normally set this. Instead, let the time format be chosen automatically according to the system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then FORMAT_24HOUR takes precedence. <p> If FORMAT_UTC is set, then the UTC timezone is used for the start and end milliseconds. <p> If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the start and end times (if shown) are abbreviated by not showing the minutes if they are zero.  For example, instead of "3:00pm" the time would be abbreviated to "3pm". <p> If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is abbreviated to a 3-letter string. <p> If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated to a 3-letter string. <p> If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown) are abbreviated to 3-letter strings. <p> If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format instead of using the name of the month.  For example, "12/31/2008" instead of "December 31, 2008".
 * @param context the context is required only if the time is shown
 * @param startMillis the start time in UTC milliseconds
 * @param endMillis the end time in UTC milliseconds
 * @param flags a bit mask of options
 * @return a string containing the formatted date/time range.
 */
public static String formatDateRange(Context context,long startMillis,long endMillis,int flags){
  Resources res=Resources.getSystem();
  boolean showTime=(flags & FORMAT_SHOW_TIME) != 0;
  boolean showWeekDay=(flags & FORMAT_SHOW_WEEKDAY) != 0;
  boolean showYear=(flags & FORMAT_SHOW_YEAR) != 0;
  boolean noYear=(flags & FORMAT_NO_YEAR) != 0;
  boolean useUTC=(flags & FORMAT_UTC) != 0;
  boolean abbrevWeekDay=(flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
  boolean abbrevMonth=(flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
  boolean noMonthDay=(flags & FORMAT_NO_MONTH_DAY) != 0;
  boolean numericDate=(flags & FORMAT_NUMERIC_DATE) != 0;
  boolean isInstant=(startMillis == endMillis);
  Time startDate=useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
  startDate.set(startMillis);
  Time endDate;
  int dayDistance;
  if (isInstant) {
    endDate=startDate;
    dayDistance=0;
  }
 else {
    endDate=useUTC ? new Time(Time.TIMEZONE_UTC) : new Time();
    endDate.set(endMillis);
    int startJulianDay=Time.getJulianDay(startMillis,startDate.gmtoff);
    int endJulianDay=Time.getJulianDay(endMillis,endDate.gmtoff);
    dayDistance=endJulianDay - startJulianDay;
  }
  if (!isInstant && (endDate.hour | endDate.minute | endDate.second) == 0 && (!showTime || dayDistance <= 1)) {
    endDate.monthDay-=1;
    endDate.normalize(true);
  }
  int startDay=startDate.monthDay;
  int startMonthNum=startDate.month;
  int startYear=startDate.year;
  int endDay=endDate.monthDay;
  int endMonthNum=endDate.month;
  int endYear=endDate.year;
  String startWeekDayString="String_Node_Str";
  String endWeekDayString="String_Node_Str";
  if (showWeekDay) {
    String weekDayFormat="String_Node_Str";
    if (abbrevWeekDay) {
      weekDayFormat=ABBREV_WEEKDAY_FORMAT;
    }
 else {
      weekDayFormat=WEEKDAY_FORMAT;
    }
    startWeekDayString=startDate.format(weekDayFormat);
    endWeekDayString=isInstant ? startWeekDayString : endDate.format(weekDayFormat);
  }
  String startTimeString="String_Node_Str";
  String endTimeString="String_Node_Str";
  if (showTime) {
    String startTimeFormat="String_Node_Str";
    String endTimeFormat="String_Node_Str";
    boolean force24Hour=(flags & FORMAT_24HOUR) != 0;
    boolean force12Hour=(flags & FORMAT_12HOUR) != 0;
    boolean use24Hour;
    if (force24Hour) {
      use24Hour=true;
    }
 else     if (force12Hour) {
      use24Hour=false;
    }
 else {
      use24Hour=DateFormat.is24HourFormat(context);
    }
    if (use24Hour) {
      startTimeFormat=endTimeFormat=res.getString(com.android.internal.R.string.hour_minute_24);
    }
 else {
      boolean abbrevTime=(flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
      boolean capAMPM=(flags & FORMAT_CAP_AMPM) != 0;
      boolean noNoon=(flags & FORMAT_NO_NOON) != 0;
      boolean capNoon=(flags & FORMAT_CAP_NOON) != 0;
      boolean noMidnight=(flags & FORMAT_NO_MIDNIGHT) != 0;
      boolean capMidnight=(flags & FORMAT_CAP_MIDNIGHT) != 0;
      boolean startOnTheHour=startDate.minute == 0 && startDate.second == 0;
      boolean endOnTheHour=endDate.minute == 0 && endDate.second == 0;
      if (abbrevTime && startOnTheHour) {
        if (capAMPM) {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_cap_ampm);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_ampm);
        }
      }
 else {
        if (capAMPM) {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.hour_minute_ampm);
        }
      }
      if (!isInstant) {
        if (abbrevTime && endOnTheHour) {
          if (capAMPM) {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_cap_ampm);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_ampm);
          }
        }
 else {
          if (capAMPM) {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.hour_minute_ampm);
          }
        }
        if (endDate.hour == 12 && endOnTheHour && !noNoon) {
          if (capNoon) {
            endTimeFormat=res.getString(com.android.internal.R.string.Noon);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.noon);
          }
        }
 else         if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
          if (capMidnight) {
            endTimeFormat=res.getString(com.android.internal.R.string.Midnight);
          }
 else {
            endTimeFormat=res.getString(com.android.internal.R.string.midnight);
          }
        }
      }
      if (startDate.hour == 12 && startOnTheHour && !noNoon) {
        if (capNoon) {
          startTimeFormat=res.getString(com.android.internal.R.string.Noon);
        }
 else {
          startTimeFormat=res.getString(com.android.internal.R.string.noon);
        }
      }
    }
    startTimeString=startDate.format(startTimeFormat);
    endTimeString=isInstant ? startTimeString : endDate.format(endTimeFormat);
  }
  if (showYear) {
  }
 else   if (noYear) {
    showYear=false;
  }
 else   if (startYear != endYear) {
    showYear=true;
  }
 else {
    Time currentTime=new Time();
    currentTime.setToNow();
    showYear=startYear != currentTime.year;
  }
  String defaultDateFormat, fullFormat, dateRange;
  if (numericDate) {
    defaultDateFormat=res.getString(com.android.internal.R.string.numeric_date);
  }
 else   if (showYear) {
    if (abbrevMonth) {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_year);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_day_year);
      }
    }
 else {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_year);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_day_year);
      }
    }
  }
 else {
    if (abbrevMonth) {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.abbrev_month_day);
      }
    }
 else {
      if (noMonthDay) {
        defaultDateFormat=res.getString(com.android.internal.R.string.month);
      }
 else {
        defaultDateFormat=res.getString(com.android.internal.R.string.month_day);
      }
    }
  }
  if (showWeekDay) {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
    }
 else {
      fullFormat=res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
    }
  }
 else {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.date1_time1_date2_time2);
    }
 else {
      fullFormat=res.getString(com.android.internal.R.string.date1_date2);
    }
  }
  if (noMonthDay && startMonthNum == endMonthNum) {
    String startDateString=startDate.format(defaultDateFormat);
    return startDateString;
  }
  if (startYear != endYear || noMonthDay) {
    String startDateString=startDate.format(defaultDateFormat);
    String endDateString=endDate.format(defaultDateFormat);
    dateRange=String.format(fullFormat,startWeekDayString,startDateString,startTimeString,endWeekDayString,endDateString,endTimeString);
    return dateRange;
  }
  String monthFormat;
  if (numericDate) {
    monthFormat=NUMERIC_MONTH_FORMAT;
  }
 else   if (abbrevMonth) {
    monthFormat=ABBREV_MONTH_FORMAT;
  }
 else {
    monthFormat=MONTH_FORMAT;
  }
  String startMonthString=startDate.format(monthFormat);
  String startMonthDayString=startDate.format(MONTH_DAY_FORMAT);
  String startYearString=startDate.format(YEAR_FORMAT);
  String endMonthString=isInstant ? null : endDate.format(monthFormat);
  String endMonthDayString=isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
  String endYearString=isInstant ? null : endDate.format(YEAR_FORMAT);
  if (startMonthNum != endMonthNum) {
    int index=0;
    if (showWeekDay)     index=1;
    if (showYear)     index+=2;
    if (showTime)     index+=4;
    if (numericDate)     index+=8;
    int resId=sameYearTable[index];
    fullFormat=res.getString(resId);
    dateRange=String.format(fullFormat,startWeekDayString,startMonthString,startMonthDayString,startYearString,startTimeString,endWeekDayString,endMonthString,endMonthDayString,endYearString,endTimeString);
    return dateRange;
  }
  if (startDay != endDay) {
    int index=0;
    if (showWeekDay)     index=1;
    if (showYear)     index+=2;
    if (showTime)     index+=4;
    if (numericDate)     index+=8;
    int resId=sameMonthTable[index];
    fullFormat=res.getString(resId);
    dateRange=String.format(fullFormat,startWeekDayString,startMonthString,startMonthDayString,startYearString,startTimeString,endWeekDayString,endMonthString,endMonthDayString,endYearString,endTimeString);
    return dateRange;
  }
  boolean showDate=(flags & FORMAT_SHOW_DATE) != 0;
  if (!showTime && !showDate && !showWeekDay)   showDate=true;
  String timeString="String_Node_Str";
  if (showTime) {
    if (isInstant) {
      timeString=startTimeString;
    }
 else {
      String timeFormat=res.getString(com.android.internal.R.string.time1_time2);
      timeString=String.format(timeFormat,startTimeString,endTimeString);
    }
  }
  fullFormat="String_Node_Str";
  String dateString="String_Node_Str";
  if (showDate) {
    dateString=startDate.format(defaultDateFormat);
    if (showWeekDay) {
      if (showTime) {
        fullFormat=res.getString(com.android.internal.R.string.time_wday_date);
      }
 else {
        fullFormat=res.getString(com.android.internal.R.string.wday_date);
      }
    }
 else {
      if (showTime) {
        fullFormat=res.getString(com.android.internal.R.string.time_date);
      }
 else {
        return dateString;
      }
    }
  }
 else   if (showWeekDay) {
    if (showTime) {
      fullFormat=res.getString(com.android.internal.R.string.time_wday);
    }
 else {
      return startWeekDayString;
    }
  }
 else   if (showTime) {
    return timeString;
  }
  dateRange=String.format(fullFormat,timeString,startWeekDayString,dateString);
  return dateRange;
}