#define timelib_conv_int(l) ((l & 0x000000ff) << 24) + ((l & 0x0000ff00) << 8) + ((l & 0x00ff0000) >> 8) + ((l & 0xff000000) >> 24)
#endif
+static void read_preamble(char **tzf, timelib_tzinfo *tz)
+{
+ /* skip ID */
+ *tzf += 4;
+
+ /* read BC flag */
+ tz->bc = (**tzf == '\1');
+ *tzf += 1;
+
+ /* read country code */
+ memcpy(tz->location.country_code, *tzf, 2);
+ tz->location.country_code[2] = '\0';
+ *tzf += 2;
+
+ /* skip read of preamble */
+ *tzf += 13;
+}
+
static void read_header(char **tzf, timelib_tzinfo *tz)
{
uint32_t buffer[6];
free(buffer);
}
+static void read_location(char **tzf, timelib_tzinfo *tz)
+{
+ uint32_t buffer[3];
+ uint32_t comments_len;
+
+ memcpy(&buffer, *tzf, sizeof(buffer));
+ tz->location.latitude = timelib_conv_int(buffer[0]);
+ tz->location.latitude = (tz->location.latitude / 100000) - 90;
+ tz->location.longitude = timelib_conv_int(buffer[1]);
+ tz->location.longitude = (tz->location.longitude / 100000) - 180;
+ comments_len = timelib_conv_int(buffer[2]);
+ *tzf += sizeof(buffer);
+
+ tz->location.comments = malloc(comments_len + 1);
+ memcpy(tz->location.comments, *tzf, comments_len);
+ tz->location.comments[comments_len] = '\0';
+ *tzf += comments_len;
+}
+
void timelib_dump_tzinfo(timelib_tzinfo *tz)
{
uint32_t i;
+ printf("Country Code: %s\n", tz->location.country_code);
+ printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
+ printf("Comments:\n%s\n", tz->location.comments);
+ printf("BC: %s\n", tz->bc ? "" : "yes");
printf("UTC/Local count: %lu\n", (unsigned long) tz->ttisgmtcnt);
printf("Std/Wall count: %lu\n", (unsigned long) tz->ttisstdcnt);
printf("Leap.sec. count: %lu\n", (unsigned long) tz->leapcnt);
} else if (cmp > 0) {
left = mid + 1;
} else { /* (cmp == 0) */
- (*tzf) = &(tzdb->data[tzdb->index[mid].pos + 20]);
+ (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
#ifdef HAVE_SETLOCALE
setlocale(LC_CTYPE, cur_locale);
if (cur_locale) free(cur_locale);
if (seek_to_tz_position(&tzf, timezone, tzdb)) {
tmp = timelib_tzinfo_ctor(timezone);
+ read_preamble((char**) &tzf, tmp);
read_header((char**) &tzf, tmp);
read_transistions((char**) &tzf, tmp);
read_types((char**) &tzf, tmp);
+ read_location((char**) &tzf, tmp);
} else {
tmp = NULL;
}
ZEND_ARG_INFO(0, timestamp_end)
ZEND_END_ARG_INFO()
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_location_get, 0, 0, 1)
+ ZEND_ARG_INFO(0, object)
+ZEND_END_ARG_INFO()
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_location_get, 0)
+ZEND_END_ARG_INFO()
+
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_timezone_identifiers_list, 0, 0, 0)
ZEND_ARG_INFO(0, what)
PHP_FE(timezone_name_from_abbr, arginfo_timezone_name_from_abbr)
PHP_FE(timezone_offset_get, arginfo_timezone_offset_get)
PHP_FE(timezone_transitions_get, arginfo_timezone_transitions_get)
+ PHP_FE(timezone_location_get, arginfo_timezone_location_get)
PHP_FE(timezone_identifiers_list, arginfo_timezone_identifiers_list)
PHP_FE(timezone_abbreviations_list, arginfo_timezone_abbreviations_list)
PHP_ME_MAPPING(getName, timezone_name_get, arginfo_timezone_method_name_get, 0)
PHP_ME_MAPPING(getOffset, timezone_offset_get, arginfo_timezone_method_offset_get, 0)
PHP_ME_MAPPING(getTransitions, timezone_transitions_get, arginfo_timezone_method_transitions_get, 0)
+ PHP_ME_MAPPING(getLocation, timezone_location_get, arginfo_timezone_method_location_get, 0)
PHP_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_timezone_abbreviations_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_timezone_identifiers_list, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
{NULL, NULL, NULL}
#define PHP_DATE_TIMEZONE_GROUP_UTC 0x0400
#define PHP_DATE_TIMEZONE_GROUP_ALL 0x07FF
#define PHP_DATE_TIMEZONE_GROUP_ALL_W_BC 0x0FFF
+#define PHP_DATE_TIMEZONE_PER_COUNTRY 0x1000
#define PHP_DATE_PERIOD_EXCLUDE_START_DATE 0x0001
REGISTER_TIMEZONE_CLASS_CONST_STRING("UTC", PHP_DATE_TIMEZONE_GROUP_UTC);
REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL", PHP_DATE_TIMEZONE_GROUP_ALL);
REGISTER_TIMEZONE_CLASS_CONST_STRING("ALL_WITH_BC", PHP_DATE_TIMEZONE_GROUP_ALL_W_BC);
+ REGISTER_TIMEZONE_CLASS_CONST_STRING("PER_COUNTRY", PHP_DATE_TIMEZONE_PER_COUNTRY);
INIT_CLASS_ENTRY(ce_interval, "DateInterval", date_funcs_interval);
ce_interval.create_object = date_object_new_interval;
}
/* }}} */
+/* {{{ proto array timezone_location_get()
+ Returns location information for a timezone, including country code, latitude/longitude and comments
+*/
+PHP_FUNCTION(timezone_location_get)
+{
+ zval *object;
+ php_timezone_obj *tzobj;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &object, date_ce_timezone) == FAILURE) {
+ RETURN_FALSE;
+ }
+ tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC);
+ DATE_CHECK_INITIALIZED(tzobj->initialized, DateTimeZone);
+ if (tzobj->type != TIMELIB_ZONETYPE_ID) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ add_assoc_string(return_value, "country_code", tzobj->tzi.tz->location.country_code, 1);
+ add_assoc_double(return_value, "latitude", tzobj->tzi.tz->location.latitude);
+ add_assoc_double(return_value, "longitude", tzobj->tzi.tz->location.longitude);
+ add_assoc_string(return_value, "comments", tzobj->tzi.tz->location.comments, 1);
+}
+/* }}} */
+
static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *format, int format_length TSRMLS_DC)
{
timelib_time *b = NULL, *e = NULL;
const timelib_tzdb_index_entry *table;
int i, item_count;
long what = PHP_DATE_TIMEZONE_GROUP_ALL;
+ char *option;
+ int option_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &what) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &what, &option, &option_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ /* Extra validation */
+ if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "A two-letter ISO 639-2 compatible country code is expected");
RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < item_count; ++i) {
- if (what == PHP_DATE_TIMEZONE_GROUP_ALL_W_BC || check_id_allowed(table[i].id, what)) {
+ if (what == PHP_DATE_TIMEZONE_PER_COUNTRY) {
+ if (tzdb->data[table[i].pos + 5] == option[0] && tzdb->data[table[i].pos + 6] == option[1]) {
+ add_next_index_string(return_value, table[i].id, 1);
+ }
+ } else if (what == PHP_DATE_TIMEZONE_GROUP_ALL_W_BC || (check_id_allowed(table[i].id, what) && (tzdb->data[table[i].pos + 4] == '\1'))) {
add_next_index_string(return_value, table[i].id, 1);
}
};