String DateTime::rfcFormat()

in hphp/runtime/base/datetime.cpp [704:837]


String DateTime::rfcFormat(const String& format) const {
  StringBuffer s;
  bool rfc_colon = false;
  bool error;
  for (int i = 0; i < format.size(); i++) {
    switch (format.charAt(i)) {
    case 'd': s.printf("%02d", day()); break;
    case 'D': s.append(shortWeekdayName()); break;
    case 'j': s.append(day()); break;
    case 'l': s.append(weekdayName()); break;
    case 'S': s.append(OrdinalSuffix(day())); break;
    case 'w': s.append(dow()); break;
    case 'N': s.append(isoDow()); break;
    case 'z': s.append(doy()); break;
    case 'W': s.printf("%02d", isoWeek()); break;
    case 'o': s.append(isoYear()); break;
    case 'F': s.append(monthName()); break;
    case 'm': s.printf("%02d", month()); break;
    case 'M': s.append(shortMonthName()); break;
    case 'n': s.append(month()); break;
    case 't': s.append(DaysInMonth(year(), month())); break;
    case 'L': s.append(IsLeap(year())); break;
    case 'y': s.printf("%02d", year() % 100); break;
    case 'Y': s.printf("%s%04d", year() < 0 ? "-" : "", abs(year()));
      break;
    case 'a': s.append(hour() >= 12 ? "pm" : "am"); break;
    case 'A': s.append(hour() >= 12 ? "PM" : "AM"); break;
    case 'B': s.printf("%03d", beat()); break;
    case 'g': s.append((hour() % 12) ? (int)hour() % 12 : 12); break;
    case 'G': s.append(hour()); break;
    case 'h': s.printf("%02d", (hour() % 12) ? (int)hour() % 12 : 12); break;
    case 'H': s.printf("%02d", (int)hour()); break;
    case 'i': s.printf("%02d", (int)minute()); break;
    case 's': s.printf("%02d", (int)second()); break;
#if TIMELIB_VERSION >= TIMELIB_MODERN
    case 'u': s.printf("%06d", (int)m_time->us); break;
    case 'v': s.printf("%03d", (int)(m_time->us / 1000)); break;
#else
    case 'u': s.printf("%06d", (int)floor(fraction() * 1000000)); break;
    case 'v': s.printf("%03d", (int)floor(fraction() * 1000)); break;
#endif
    case 'I': s.append(!utc() && m_tz->dst(toTimeStamp(error)) ? 1 : 0);
      break;
    case 'P': rfc_colon = true; /* break intentionally missing */
    case 'O':
      if (utc()) {
        s.printf("+00%s00", rfc_colon ? ":" : "");
      } else {
        int offset = this->offset();
        s.printf("%c%02d%s%02d",
                 (offset < 0 ? '-' : '+'), abs(offset / 3600),
                 rfc_colon ? ":" : "", abs((offset % 3600) / 60));
      }
      break;
    case 'T':
      if (utc()) {
        s.append("GMT");
      } else {
        if (m_time->zone_type != TIMELIB_ZONETYPE_OFFSET) {
          s.append(m_time->tz_abbr);
        } else {
#if TIMELIB_VERSION >= TIMELIB_MODERN
          auto offset = m_time->z;
#else
          auto offset = m_time->z * -60;
#endif

          char abbr[9] = {0};
          snprintf(abbr, 9, "GMT%c%02d%02d",
            ((offset < 0) ? '-' : '+'),
            abs(offset / 3600) % 100, // % 100 to convince compiler we have 2 digits
            abs((offset % 3600) / 60));
          s.append(abbr);
        }
      }
      break;
    case 'e':
      if (utc()) {
        s.append("UTC");
      } else {
        if (m_time->zone_type != TIMELIB_ZONETYPE_OFFSET) {
          s.append(m_tz->name());
        } else {
#if TIMELIB_VERSION >= TIMELIB_MODERN
          auto offset = m_time->z;
#else
          auto offset = m_time->z * -60;
#endif
          char abbr[7] = {0};
          snprintf(abbr, 7, "%c%02d:%02d",
            ((offset < 0) ? '-' : '+'),
            abs(offset / 3600) % 100, // % 100 to convince compiler we have 2 digits
            abs((offset % 3600) / 60));
          s.append(abbr);
        }
      }
      break;
    case 'Z': s.append(utc() ? 0 : this->offset()); break;
    case 'c':
      if (utc()) {
        s.printf("%04d-%02d-%02dT%02d:%02d:%02d+00:00",
                 year(), month(), day(), hour(), minute(), second());
      } else {
        int offset = this->offset();
        s.printf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
                 year(), month(), day(), hour(), minute(), second(),
                 (offset < 0 ? '-' : '+'),
                 abs(offset / 3600), abs((offset % 3600) / 60));
      }
      break;
    case 'r':
      if (utc()) {
        s.printf("%3s, %02d %3s %04d %02d:%02d:%02d +0000",
                 shortWeekdayName(), day(), shortMonthName(), year(),
                 hour(), minute(), second());
      } else {
        int offset = this->offset();
        s.printf("%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
                 shortWeekdayName(), day(), shortMonthName(), year(),
                 hour(), minute(), second(),
                 (offset < 0 ? '-' : '+'),
                 abs(offset / 3600), abs((offset % 3600) / 60));
      }
      break;
    case 'U': s.printf("%" PRId64, toTimeStamp(error)); break;
    case '\\':
      if (i < format.size()) i++; /* break intentionally missing */
    default:
      s.append(format[i]);
      break;
    }
  }
  return s.detach();
}