php-src/ext/intl/dateformat/dateformat_helpers.cpp
Gustavo André dos Santos Lopes eb346ef0f4 DateFormat plays nice with Calendar, TimeZone
The following changes were made:

* The IntlDateFormatter constructor now accepts the usual values
  for its $timezone argument. This includes timezone identifiers,
  IntlTimeZone objects, DateTimeZone objects and NULL. An empty
  string is not accepted. An invalid time zone is no longer accepted
  (it used to use UTC in this case).
* When NULL is passed to IntlDateFormatter, the time zone specified in
  date.timezone is used instead of the ICU default.
* The IntlDateFormatter $calendar argument now accepts also an
  IntlCalendar. In this case, IntlDateFormatter::getCalendar() will
  return false.
* The time zone passed to the IntlDateFormatter is ignored if it is
  NULL and if the calendar passed is an IntlCalendar object -- in this
  case, the IntlCalendar time zone will be used instead. Otherwise,
  the time zone specified in the $timezone argument is used instead.
* Added IntlDateFormatter::getCalendarObject(), which always returns
  the IntlCalendar object that backs the DateFormat, even if a
  constant was passed to the constructor, i.e., if an IntlCalendar
  was not passed to the constructor.
* Added IntlDateFormatter::setTimeZone(). It accepts the usual values
  for time zone arguments. If NULL is passed, the time zone of the
  IntlDateFormatter WILL be overridden with the default time zone,
  even if an IntlCalendar object was passed to the constructor.
* Added IntlDateFormatter::getTimeZone(), which returns the time zone
  that's associated with the DateFormat.
* Depreacated IntlDateFormatter::setTimeZoneId() and made it an alias
  for IntlDateFormatter::setTimeZone(), as the new ::setTimeZone()
  also accepts plain identifiers, besides other types.
  IntlDateFormatter::getTimeZoneId() is not deprecated however.
* IntlDateFormatter::setCalendar() with a constant passed should now
  work correctly. This requires saving the requested locale to the
  constructor.
* Centralized the hacks required to avoid compilation disasters on
  Windows due to some headers being included inside and outside of
  extern "C" blocks.
2012-06-04 00:01:48 +02:00

107 lines
3.4 KiB
C++

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#include "../intl_cppshims.h"
#include <unicode/calendar.h>
#include <unicode/gregocal.h>
#include "dateformat_helpers.h"
extern "C" {
#include "../php_intl.h"
#include <Zend/zend_operators.h>
#define USE_CALENDAR_POINTER 1
#include "../calendar/calendar_class.h"
}
int datefmt_process_calendar_arg(zval* calendar_zv,
Locale const& locale,
const char *func_name,
intl_error *err,
Calendar*& cal,
long& cal_int_type,
bool& calendar_owned TSRMLS_DC)
{
char *msg;
UErrorCode status = UErrorCode();
if (calendar_zv == NULL || Z_TYPE_P(calendar_zv) == IS_NULL) {
// default requested
cal = new GregorianCalendar(locale, status);
calendar_owned = true;
cal_int_type = UCAL_GREGORIAN;
} else if (Z_TYPE_P(calendar_zv) == IS_LONG) {
long v = Z_LVAL_P(calendar_zv);
if (v != (long)UCAL_TRADITIONAL && v != (long)UCAL_GREGORIAN) {
spprintf(&msg, 0, "%s: invalid value for calendar type; it must be "
"one of IntlDateFormatter::TRADITIONAL (locale's default "
"calendar) or IntlDateFormatter::GREGORIAN. "
"Alternatively, it can be an IntlCalendar object",
func_name);
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
return FAILURE;
} else if (v == (long)UCAL_TRADITIONAL) {
cal = Calendar::createInstance(locale, status);
} else { //UCAL_GREGORIAN
cal = new GregorianCalendar(locale, status);
}
calendar_owned = true;
cal_int_type = Z_LVAL_P(calendar_zv);
} else if (Z_TYPE_P(calendar_zv) == IS_OBJECT &&
instanceof_function_ex(Z_OBJCE_P(calendar_zv),
Calendar_ce_ptr, 0 TSRMLS_CC)) {
cal = calendar_fetch_native_calendar(calendar_zv TSRMLS_CC);
if (cal == NULL) {
spprintf(&msg, 0, "%s: Found unconstructed IntlCalendar object",
func_name);
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
return FAILURE;
}
calendar_owned = false;
cal_int_type = -1;
} else {
spprintf(&msg, 0, "%s: Invalid calendar argument; should be an integer "
"or an IntlCalendar instance", func_name);
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
return FAILURE;
}
if (cal == NULL && !U_FAILURE(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) {
spprintf(&msg, 0, "%s: Failure instantiating calendar", func_name);
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, msg, 1 TSRMLS_CC);
efree(msg);
return FAILURE;
}
return SUCCESS;
}