a8e3321fbd
We'd like to start using ##mixed## instead of ##var## for attribute types to be consistent with Hack. As a followup to this (once released), we would codemod all ##var## to ##mixed##.
363 linhas
12 KiB
C++
363 linhas
12 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
|
|
| Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.zend.com/license/2_00.txt. |
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#ifndef incl_HPHP_DATETIME_H_
|
|
#define incl_HPHP_DATETIME_H_
|
|
|
|
#include "hphp/runtime/base/types.h"
|
|
#include "hphp/runtime/base/timezone.h"
|
|
#include "hphp/runtime/base/dateinterval.h"
|
|
#include "hphp/runtime/base/request_local.h"
|
|
|
|
namespace HPHP {
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Encapsulating all date/time manipulations, conversions, input and output
|
|
* into this one single class.
|
|
*/
|
|
class DateTime : public SweepableResourceData {
|
|
public:
|
|
DECLARE_OBJECT_ALLOCATION(DateTime);
|
|
|
|
/**
|
|
* Different RFC/ISO date/time formats for toString(DateFormat).
|
|
*/
|
|
enum class DateFormat {
|
|
InvalidFormat,
|
|
|
|
/**
|
|
* RFC822, Section 5.1: http://www.ietf.org/rfc/rfc822.txt
|
|
* date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz
|
|
* day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
|
|
* date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82
|
|
* month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
|
|
* "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
|
|
* time = hour zone ; ANSI and Military
|
|
* hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
|
|
* zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" / "MST" /
|
|
* "MDT" / "PST" / "PDT" / 1ALPHA / (("+" / "-") 4DIGIT)
|
|
*/
|
|
RFC822,
|
|
|
|
/**
|
|
* RFC850, Section 2.1.4: http://www.ietf.org/rfc/rfc850.txt
|
|
* Format must be acceptable both to the ARPANET and to the getdate
|
|
* routine. One format that is acceptable to both is Weekday,
|
|
* DD-Mon-YY HH:MM:SS TIMEZONE
|
|
* TIMEZONE can be any timezone name (3 or more letters)
|
|
*/
|
|
RFC850,
|
|
|
|
/**
|
|
* RFC1036, Section 2.1.2: http://www.ietf.org/rfc/rfc1036.txt
|
|
* Its format must be acceptable both in RFC-822 and to the getdate(3)
|
|
* Wdy, DD Mon YY HH:MM:SS TIMEZONE
|
|
* There is no hope of having a complete list of timezones. Universal
|
|
* Time (GMT), the North American timezones (PST, PDT, MST, MDT, CST,
|
|
* CDT, EST, EDT) and the +/-hhmm offset specifed in RFC-822 should be
|
|
* supported.
|
|
*/
|
|
RFC1036,
|
|
|
|
/**
|
|
* RFC1123, Section 5.2.14: http://www.ietf.org/rfc/rfc1123.txt
|
|
* RFC-822 Date and Time Specification: RFC-822 Section 5
|
|
* The syntax for the date is hereby changed to:
|
|
* date = 1*2DIGIT month 2*4DIGIT
|
|
*/
|
|
RFC1123,
|
|
|
|
/**
|
|
* RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt
|
|
* FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space
|
|
* CFWS = *([FWS] comment) (([FWS] comment) / FWS)
|
|
*
|
|
* date-time = [ day-of-week "," ] date FWS time [CFWS]
|
|
* day-of-week = ([FWS] day-name)
|
|
* day-name = "Mon"/"Tue"/"Wed"/"Thu"/"Fri"/"Sat"/"Sun"
|
|
* date = day month year
|
|
* year = 4*DIGIT
|
|
* month = (FWS month-name FWS)
|
|
* month-name = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
|
|
* "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
|
|
* day = ([FWS] 1*2DIGIT)
|
|
* time = time-of-day FWS zone
|
|
* time-of-day = hour ":" minute [ ":" second ]
|
|
* hour = 2DIGIT
|
|
* minute = 2DIGIT
|
|
* second = 2DIGIT
|
|
* zone = (( "+" / "-" ) 4DIGIT)
|
|
*/
|
|
RFC2822,
|
|
|
|
/**
|
|
* RFC3339, Section 5.6: http://www.ietf.org/rfc/rfc3339.txt
|
|
* date-fullyear = 4DIGIT
|
|
* date-month = 2DIGIT ; 01-12
|
|
* date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
|
|
* ; month/year
|
|
*
|
|
* time-hour = 2DIGIT ; 00-23
|
|
* time-minute = 2DIGIT ; 00-59
|
|
* time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on
|
|
* ; leap second rules
|
|
*
|
|
* time-secfrac = "." 1*DIGIT
|
|
* time-numoffset = ("+" / "-") time-hour ":" time-minute
|
|
* time-offset = "Z" / time-numoffset
|
|
*
|
|
* partial-time = time-hour ":" time-minute ":" time-second
|
|
* [time-secfrac]
|
|
* full-date = date-fullyear "-" date-month "-" date-mday
|
|
* full-time = partial-time time-offset
|
|
*
|
|
* date-time = full-date "T" full-time
|
|
*/
|
|
RFC3339,
|
|
|
|
ISO8601,
|
|
|
|
/**
|
|
* Preliminary specification:
|
|
* http://wp.netscape.com/newsref/std/cookie_spec.html
|
|
* "This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123,
|
|
* with the variations that the only legal time zone is GMT
|
|
* and the separators between the elements of the date must be dashes."
|
|
*/
|
|
Cookie,
|
|
|
|
/**
|
|
* Similar to Cookie without dashes.
|
|
*/
|
|
HttpHeader,
|
|
|
|
/**
|
|
* RFC4287, Section 3.3: http://www.ietf.org/rfc/rfc4287.txt
|
|
* A Date construct is an element whose content MUST conform to the
|
|
* "date-time" production in [RFC3339]. In addition, an uppercase "T"
|
|
* character MUST be used to separate date and time, and an uppercase
|
|
* "Z" character MUST be present in the absence of a numeric time zone
|
|
* offset.
|
|
*/
|
|
Atom = RFC3339,
|
|
|
|
/**
|
|
* RSS 2.0 Specification: http://blogs.law.harvard.edu/tech/rss
|
|
* "All date-times in RSS conform to the Date and Time Specification of
|
|
* RFC 822, with the exception that the year may be expressed with two
|
|
* characters or four characters (four preferred)"
|
|
*/
|
|
RSS = RFC1123,
|
|
|
|
W3C = RFC3339,
|
|
};
|
|
|
|
/**
|
|
* Different array formats for toArray().
|
|
*/
|
|
enum class ArrayFormat {
|
|
TimeMap,
|
|
TmMap,
|
|
TmVector
|
|
};
|
|
|
|
/**
|
|
* Different formats for getSunInfo().
|
|
*/
|
|
enum class SunInfoFormat {
|
|
ReturnTimeStamp,
|
|
ReturnString,
|
|
ReturnDouble
|
|
};
|
|
|
|
public:
|
|
static const char *DateFormatRFC822;
|
|
static const char *DateFormatRFC850;
|
|
static const char *DateFormatRFC1036;
|
|
static const char *DateFormatRFC1123;
|
|
static const char *DateFormatRFC2822;
|
|
static const char *DateFormatRFC3339;
|
|
static const char *DateFormatISO8601;
|
|
static const char *DateFormatCookie;
|
|
static const char *DateFormatHttpHeader;
|
|
|
|
static const char *MonthNames[];
|
|
static const char *ShortMonthNames[];
|
|
static const char *WeekdayNames[];
|
|
static const char *ShortWeekdayNames[];
|
|
|
|
static const char *GetWeekdayName(int y, int m, int d);
|
|
static const char *GetShortWeekdayName(int y, int m, int d);
|
|
static const char *OrdinalSuffix(int number);
|
|
|
|
static bool IsLeap(int year);
|
|
static int DaysInMonth(int y, int m);
|
|
static bool IsValid(int y, int m, int d);
|
|
|
|
/**
|
|
* What time is it?
|
|
*/
|
|
static SmartResource<DateTime> Current(bool utc = false);
|
|
|
|
/**
|
|
* Returns are really in special PHP formats, and please read datetime.cpp
|
|
* for details.
|
|
*/
|
|
static Array Parse(CStrRef datetime);
|
|
static Array Parse(CStrRef ts, CStrRef format);
|
|
|
|
public:
|
|
// constructor
|
|
DateTime();
|
|
explicit DateTime(int64_t timestamp, bool utc = false); // from a timestamp
|
|
|
|
static StaticString s_class_name;
|
|
// overriding ResourceData
|
|
CStrRef o_getClassNameHook() const { return s_class_name; }
|
|
|
|
// informational
|
|
bool local() const { return m_time->is_localtime;}
|
|
bool utc() const { return !m_time->is_localtime;}
|
|
int year() const { return m_time->y;}
|
|
int month() const { return m_time->m;}
|
|
int day() const { return m_time->d;}
|
|
int hour() const { return m_time->h;}
|
|
int hour12() const { return (m_time->h % 12) ? (int) m_time->h % 12 : 12;}
|
|
int minute() const { return m_time->i;}
|
|
int second() const { return m_time->s;}
|
|
double fraction() const { return m_time->f;}
|
|
int beat() const; // Swatch Beat a.k.a. Internet Time
|
|
int dow() const; // day of week
|
|
int doy() const; // day of year
|
|
int isoWeek() const;
|
|
int isoYear() const;
|
|
int isoDow() const;
|
|
int offset() const; // timezone offset from UTC
|
|
SmartResource<TimeZone> timezone() const { return m_tz->cloneTimeZone();}
|
|
|
|
const char *weekdayName() const;
|
|
const char *shortWeekdayName() const;
|
|
const char *monthName() const;
|
|
const char *shortMonthName() const;
|
|
|
|
// modifications
|
|
void set(int hour, int minute, int second, int month, int day, int year);
|
|
void setDate(int year, int month, int day);
|
|
void setISODate(int year, int week, int day = 1);
|
|
void setTime(int hour, int minute, int second = 0);
|
|
void setTimezone(SmartResource<TimeZone> tz);
|
|
void modify(CStrRef diff); // PHP's date_modify() function, very powerful
|
|
void add(const SmartResource<DateInterval> &interval);
|
|
void sub(const SmartResource<DateInterval> &interval);
|
|
void internalModify(timelib_rel_time *rel, bool have_relative, char bias);
|
|
|
|
// conversions
|
|
void toTm(struct tm &ta) const;
|
|
int64_t toTimeStamp(bool &err) const;
|
|
int64_t toInteger(char format) const;
|
|
String toString(CStrRef format, bool stdc = false) const;
|
|
String toString(DateFormat format) const;
|
|
Array toArray(ArrayFormat format) const;
|
|
void fromTimeStamp(int64_t timestamp, bool utc = false);
|
|
bool fromString(CStrRef input, SmartResource<TimeZone> tz,
|
|
const char* format=nullptr);
|
|
|
|
// comparison
|
|
SmartResource<DateInterval> diff(SmartResource<DateTime> datetime2,
|
|
bool absolute = false);
|
|
|
|
// cloning
|
|
SmartResource<DateTime> cloneDateTime() const;
|
|
|
|
// sun info
|
|
Array getSunInfo(double latitude, double longitude) const;
|
|
Variant getSunInfo(SunInfoFormat retformat,
|
|
double latitude, double longitude,
|
|
double zenith, double utc_offset, bool calc_sunset) const;
|
|
|
|
// Error access
|
|
private:
|
|
class LastErrors : public RequestEventHandler {
|
|
public:
|
|
virtual void requestInit() {
|
|
m_errors = nullptr;
|
|
}
|
|
virtual void requestShutdown() {
|
|
if (m_errors) {
|
|
timelib_error_container_dtor(m_errors);
|
|
}
|
|
}
|
|
void set(timelib_error_container *ec) {
|
|
requestShutdown();
|
|
m_errors = ec;
|
|
}
|
|
Array getLastWarnings() {
|
|
Array ret = Array::Create();
|
|
if (!m_errors) return ret;
|
|
for(int i = 0; i < m_errors->warning_count; i++) {
|
|
timelib_error_message *em = m_errors->warning_messages + i;
|
|
ret.set(em->position, String(em->message, CopyString));
|
|
}
|
|
return ret;
|
|
}
|
|
Array getLastErrors() {
|
|
Array ret = Array::Create();
|
|
if (!m_errors) return ret;
|
|
for(int i = 0; i < m_errors->error_count; i++) {
|
|
timelib_error_message *em = m_errors->error_messages + i;
|
|
ret.set(em->position, String(em->message, CopyString));
|
|
}
|
|
return ret;
|
|
}
|
|
private:
|
|
timelib_error_container *m_errors;
|
|
};
|
|
DECLARE_STATIC_REQUEST_LOCAL(LastErrors, s_lastErrors);
|
|
|
|
public:
|
|
static void setLastErrors(timelib_error_container *ec)
|
|
{ s_lastErrors.get()->set(ec); }
|
|
static Array getLastWarnings()
|
|
{ return s_lastErrors.get()->getLastWarnings(); }
|
|
static Array getLastErrors()
|
|
{ return s_lastErrors.get()->getLastErrors(); }
|
|
|
|
private:
|
|
struct time_deleter {
|
|
void operator()(timelib_time *t) {
|
|
timelib_time_dtor(t);
|
|
}
|
|
};
|
|
typedef boost::shared_ptr<timelib_time> TimePtr;
|
|
|
|
TimePtr m_time;
|
|
SmartResource<TimeZone> m_tz;
|
|
mutable int64_t m_timestamp;
|
|
mutable bool m_timestampSet;
|
|
|
|
// helpers
|
|
void update();
|
|
String rfcFormat(CStrRef format) const;
|
|
String stdcFormat(CStrRef format) const;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
#endif // incl_HPHP_DATETIME_H_
|