Browse Source

- MFH: Added support for selectively listing timezone identifiers by country

code through timezone_identifiers_list() / DateTimezone::listIdentifiers().
- MFH: Added timezone_location_get() / DateTimezone::getLocation() for
  retrieving location information from timezones.
PECL
Derick Rethans 18 years ago
parent
commit
84693147d0
  1. 7
      NEWS
  2. 45
      ext/date/lib/parse_tz.c
  3. 10
      ext/date/lib/timelib_structs.h
  4. 54
      ext/date/php_date.c
  5. 1
      ext/date/php_date.h

7
NEWS

@ -135,8 +135,11 @@ PHP NEWS
. date_parse_from_format()
. support for abbreviation and offset based timezone specifiers for
DateTime::getOffset() and DateTime::getName().
. support for selectively listing timezone identifiers through
timezone_identifiers_list() / DateTimezone::listIdentifiers().
. support for selectively listing timezone identifiers by continent or
country code through timezone_identifiers_list() /
DateTimezone::listIdentifiers().
. timezone_location_get() / DateTimezone::getLocation() for retrieving
location information from timezones.
. date_timestamp_set() / DateTime::setTimestamp() to set a Unix timestamp
without invoking the date parser. (Scott)
. date_timestamp_get() / DateTime::getTimestamp() to retrieve the Unix

45
ext/date/lib/parse_tz.c

@ -49,6 +49,24 @@
#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];
@ -167,10 +185,33 @@ static void read_types(char **tzf, timelib_tzinfo *tz)
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);
@ -228,7 +269,7 @@ static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const
} 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);
@ -270,9 +311,11 @@ timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
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;
}

10
ext/date/lib/timelib_structs.h

@ -97,6 +97,14 @@ typedef struct tlinfo
int32_t offset;
} tlinfo;
typedef struct tlocinfo
{
char country_code[3];
double latitude;
double longitude;
char *comments;
} tlocinfo;
typedef struct timelib_tzinfo
{
char *name;
@ -114,6 +122,8 @@ typedef struct timelib_tzinfo
char *timezone_abbr;
tlinfo *leap_times;
unsigned char bc;
tlocinfo location;
} timelib_tzinfo;
typedef struct timelib_special {

54
ext/date/php_date.c

@ -370,6 +370,15 @@ ZEND_BEGIN_ARG_INFO(arginfo_timezone_method_transitions_get, 0)
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)
@ -451,6 +460,7 @@ const zend_function_entry date_functions[] = {
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)
@ -495,6 +505,7 @@ const zend_function_entry date_funcs_timezone[] = {
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}
@ -1823,6 +1834,7 @@ PHP_FUNCTION(getdate)
#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
@ -2025,6 +2037,7 @@ static void date_register_classes(TSRMLS_D)
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;
@ -3356,6 +3369,31 @@ PHP_FUNCTION(timezone_transitions_get)
}
/* }}} */
/* {{{ 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;
@ -3734,8 +3772,16 @@ PHP_FUNCTION(timezone_identifiers_list)
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;
}
@ -3746,7 +3792,11 @@ PHP_FUNCTION(timezone_identifiers_list)
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);
}
};

1
ext/date/php_date.h

@ -76,6 +76,7 @@ PHP_FUNCTION(timezone_name_get);
PHP_FUNCTION(timezone_name_from_abbr);
PHP_FUNCTION(timezone_offset_get);
PHP_FUNCTION(timezone_transitions_get);
PHP_FUNCTION(timezone_location_get);
PHP_FUNCTION(timezone_identifiers_list);
PHP_FUNCTION(timezone_abbreviations_list);

Loading…
Cancel
Save