Ejemplo n.º 1
0
U_CFUNC PHP_FUNCTION(datefmt_format_object)
{
	zval				*object,
						*format = NULL;
	const char			*locale_str	= NULL;
	size_t					locale_len;
	bool				pattern		= false;
	UDate				date;
	TimeZone			*timeZone	= NULL;
	UErrorCode			status		= U_ZERO_ERROR;
	DateFormat			*df			= NULL;
	Calendar			*cal		= NULL;
	DateFormat::EStyle	dateStyle = DateFormat::kDefault,
						timeStyle = DateFormat::kDefault;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|zs!",
			&object, &format, &locale_str, &locale_len) == FAILURE) {
		RETURN_FALSE;
	}

	if (!locale_str) {
		locale_str = intl_locale_get_default();
	}

	if (format == NULL || Z_TYPE_P(format) == IS_NULL) {
		//nothing
	} else if (Z_TYPE_P(format) == IS_ARRAY) {
		HashTable		*ht	= Z_ARRVAL_P(format);
		HashPosition	pos	= {0};
		zval			*z;
		if (zend_hash_num_elements(ht) != 2) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: bad format; if array, it must have "
					"two elements", 0);
			RETURN_FALSE;
		}

		zend_hash_internal_pointer_reset_ex(ht, &pos);
		z = zend_hash_get_current_data_ex(ht, &pos);
		if (!valid_format(z)) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: bad format; the date format (first "
					"element of the array) is not valid", 0);
			RETURN_FALSE;
		}
		dateStyle = (DateFormat::EStyle)Z_LVAL_P(z);

		zend_hash_move_forward_ex(ht, &pos);
		z = zend_hash_get_current_data_ex(ht, &pos);
		if (!valid_format(z)) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: bad format; the time format ("
					"second element of the array) is not valid", 0);
			RETURN_FALSE;
		}
		timeStyle = (DateFormat::EStyle)Z_LVAL_P(z);
	} else if (Z_TYPE_P(format) == IS_LONG) {
		if (!valid_format(format)) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: the date/time format type is invalid",
					0);
			RETURN_FALSE;
		}
		dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format);
	} else {
		convert_to_string_ex(format);
		if (Z_STRLEN_P(format) == 0) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: the format is empty", 0);
			RETURN_FALSE;
		}
		pattern = true;
	}

	//there's no support for relative time in ICU yet
	timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative);

	zend_class_entry *instance_ce = Z_OBJCE_P(object);
	if (instanceof_function(instance_ce, Calendar_ce_ptr)) {
		Calendar *obj_cal = calendar_fetch_native_calendar(object);
		if (obj_cal == NULL) {
			intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
					"datefmt_format_object: bad IntlCalendar instance: "
					"not initialized properly", 0);
			RETURN_FALSE;
		}
		timeZone = obj_cal->getTimeZone().clone();
		date = obj_cal->getTime(status);
		if (U_FAILURE(status)) {
			intl_error_set(NULL, status,
					"datefmt_format_object: error obtaining instant from "
					"IntlCalendar", 0);
			RETVAL_FALSE;
			goto cleanup;
		}
		cal = obj_cal->clone();
	} else if (instanceof_function(instance_ce, php_date_get_date_ce())) {
		if (intl_datetime_decompose(object, &date, &timeZone, NULL,
				"datefmt_format_object") == FAILURE) {
			RETURN_FALSE;
		}
		cal = new GregorianCalendar(Locale::createFromName(locale_str), status);
		if (U_FAILURE(status)) {
			intl_error_set(NULL, status,
					"datefmt_format_object: could not create GregorianCalendar",
					0);
			RETVAL_FALSE;
			goto cleanup;
		}
	} else {
		intl_error_set(NULL, status, "datefmt_format_object: the passed object "
				"must be an instance of either IntlCalendar or DateTime",
				0);
		RETURN_FALSE;
	}

	if (pattern) {
		 df = new SimpleDateFormat(
				UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format),
						UnicodeString::kInvariant),
				Locale::createFromName(locale_str),
				status);

		if (U_FAILURE(status)) {
			intl_error_set(NULL, status,
					"datefmt_format_object: could not create SimpleDateFormat",
					0);
			RETVAL_FALSE;
			goto cleanup;
		}
	} else {
		df = DateFormat::createDateTimeInstance(dateStyle, timeStyle,
				Locale::createFromName(locale_str));

		if (df == NULL) { /* according to ICU sources, this should never happen */
			intl_error_set(NULL, status,
					"datefmt_format_object: could not create DateFormat",
					0);
			RETVAL_FALSE;
			goto cleanup;
		}
	}

	//must be in this order (or have the cal adopt the tz)
	df->adoptCalendar(cal);
	cal = NULL;
	df->adoptTimeZone(timeZone);
	timeZone = NULL;

	{
		char *ret_str;
		int ret_str_len;
		UnicodeString result = UnicodeString();
		df->format(date, result);

		if (intl_charFromString(result, &ret_str, &ret_str_len, &status) == FAILURE) {
			intl_error_set(NULL, status,
					"datefmt_format_object: error converting result to UTF-8",
					0);
			RETVAL_FALSE;
			goto cleanup;
		}
		RETVAL_STRINGL(ret_str, ret_str_len);
		//???
		efree(ret_str);
	}


cleanup:
	delete df;
	delete timeZone;
	delete cal;
}
Ejemplo n.º 2
0
U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
{
	zval			**zv_arg,
					*zv_datetime		= NULL;
	double			millis;
	php_date_obj	*datetime;
	char			*locale_str			= NULL;
	int				locale_str_len;
	TimeZone		*timeZone;
	UErrorCode		status				= U_ZERO_ERROR;
	Calendar        *cal;
	intl_error_reset(NULL TSRMLS_CC);

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s!",
			&zv_arg, &locale_str, &locale_str_len) == FAILURE) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_from_date_time: bad arguments", 0 TSRMLS_CC);
		RETURN_NULL();
	}

	if (!(Z_TYPE_PP(zv_arg) == IS_OBJECT && instanceof_function(
			Z_OBJCE_PP(zv_arg), php_date_get_date_ce() TSRMLS_CC))) {
		ALLOC_INIT_ZVAL(zv_datetime);
		object_init_ex(zv_datetime, php_date_get_date_ce());
		zend_call_method_with_1_params(&zv_datetime, NULL, NULL, "__construct",
			NULL, *zv_arg);
		if (EG(exception)) {
			zend_object_store_ctor_failed(zv_datetime TSRMLS_CC);
			goto error;
		}
	} else {
		zv_datetime = *zv_arg;
	}

	datetime = (php_date_obj*)zend_object_store_get_object(zv_datetime TSRMLS_CC);
	if (!datetime->time) {
		intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"intlcal_from_date_time: DateTime object is unconstructed",
			0 TSRMLS_CC);
		goto error;
	}

	if (intl_datetime_decompose(zv_datetime, &millis, NULL, NULL,
			 "intlcal_from_date_time" TSRMLS_CC) == FAILURE) {
		goto error;
	}

	if (!datetime->time->is_localtime) {
		timeZone = TimeZone::getGMT()->clone();
	} else {
		timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
			datetime, 1, NULL, "intlcal_from_date_time" TSRMLS_CC);
		if (timeZone == NULL) {
			goto error;
		}
	}

	if (!locale_str) {
		locale_str = const_cast<char*>(intl_locale_get_default(TSRMLS_C));
	}

	cal = Calendar::createInstance(timeZone,
		Locale::createFromName(locale_str), status);
	if (cal == NULL) {
		delete timeZone;
		intl_error_set(NULL, status, "intlcal_from_date_time: "
				"error creating ICU Calendar object", 0 TSRMLS_CC);
		goto error;
	}
	cal->setTime(millis, status);
    if (U_FAILURE(status)) {
		/* time zone was adopted by cal; should not be deleted here */
		delete cal;
		intl_error_set(NULL, status, "intlcal_from_date_time: "
				"error creating ICU Calendar::setTime()", 0 TSRMLS_CC);
        goto error;
    }

	calendar_object_create(return_value, cal TSRMLS_CC);

error:
	if (zv_datetime != *zv_arg) {
		zval_ptr_dtor(&zv_datetime);
	}
}