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();
}