DrHyde / perl-modules-Number-Phone

Number::Phone and friends

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support timezone mappings

percivalalb opened this issue · comments

AFAICT Number::Phone does not support mapping a phone number to it's assoicated geographic timezone/s.

The libphonenumber project by Google which this project uses provides the data needed for this resources/timezones/map_data.txt.

Other ports in other programming languages do support this, for example:

I envision a method like the following:

Number::Phone->new("+1202-555-0000")->timezones;' # ('America/New_York')

Given that the libphonenumber generated stubs will have access to this data and to maintain backwards compatibility, if a stub doesn't implement the timezones method it should fall back to the libphonenumber data.

I plan to write more of my thoughts on this issue and develop the solution with your permission.

I'd certainly consider a patch that adds this.

There's a tricky little problem regarding those places which Google list as Foo/Bar&Baz/Barf - ie a number range covers two time zones. I think in the general case those should:

  • return the list of zones if the object is one of the stubs generated entirely from libphonenumber data (presumably with the implementation in N::P::StubCountry);
  • otherwise should have a method in the N::P base class which is careful about those multi-timezone ranges

I think the best thing to do would be to examine all the timezones in the &-separated list and see if they are currently identical, and if they are return the most important of them. eg for Europe/Guernsey&Europe/Isle_of_Man&Europe/Jersey&Europe/London it should return ('Europe/London') because those are all currently identical. They only have different names because historically they handled summer time madness differently. How you tell which is most important I'm not sure. Perhaps the one which has a mapping on its own for the shortest prefix excluding the country code, with undef if there is no such unique best guess? We'd need very comprehensive tests for this! To tell if two timezones are currently identical, errm, excellent question. It's in the Olson tz database somewhere I'm sure but I have no idea where! DateTime::TimeZone->links is a partial but incomplete solution. But if that seems too much like hard work, doing as Google does would be fine too, I can always refine it later while remaining API-compatible.

Oh, and it's a very common error in perl code to use a function in scalar context when it returns a list. I think the method should always return a list-ref instead of a list, so that there's no possibility of accidentally dropping data on the floor.

they handled summer time madness differently

My favourite!

I think the method should always return a list-ref instead of a list, so that there's no possibility of accidentally dropping data on the floor.

I'm familiar with these perl whoes, perhaps in scalar context return a list-ref and in list context a list? Regardless if always a list-ref matches the rest of the module that sounds good.

my ($first) = Number::Phone->new("+1202-555-0000")->timezones;' # 'America/New_York'
my @list Number::Phone->new("+1202-555-0000")->timezones;' # ('America/New_York')
my $ref = Number::Phone->new("+1202-555-0000")->timezones;' # ['America/New_York']

Regardless if always a list-ref matches the rest of the module that sounds good.

DateTime::TimeZone->links is a partial but incomplete solution.

By incomplete do you mean that it will solve the easy case where the timezone name is identical but does't solve the case where the timezone name is different but still represents the same underlying timezone.

Following DateTime::TimeZone->links -> DateTime::TimeZone::Catalog%LINKS

Guernsey & Isle_of_Man are mapped to London as their new names, so this methodigy would solve the UKs timezones: UK tz mapping


I'm yet to check the coverage of this theory, so may fall flat on it's face:

  • Download and parse a map of country code -> capitial city
  • Determine the country code of each line in map_data.txt. (I think it should be possible)
  • Use DateTime::TimeZone->links to map any deprecated names to new.
  • Remove duplicate timezone names
  • Compare different timezones names if they are the same underlying timezone now. (But how)?
  • If so remove all but the capitial of the country

I could see how far this gets us anyway.

Examples

Take the lines:

  • 47|Arctic/Longyearbyen&Europe/Oslo
  • 4477|Europe/Guernsey&Europe/Isle_of_Man&Europe/London
  • 3518|Atlantic/Azores&Europe/Lisbon

Arctic/Longyearbyen translates to Europe/Berlin (deprecated to new name)
Europe/Guernsey & Europe/Isle_of_Man translates to Europe/London (deprecated to new name)

  • 47|Europe/Berlin&Europe/Oslo
  • 4477|Europe/London
  • 3518|Europe/Lisbon

I'm unsure if Europe/Berlin & Europe/Oslo represente the same underlying timezone - from a quick look I believe they do.

47 country code is Norway with captial Oslo, so we choose Europe/Oslo
351 country code is Portugal with captial Lisbon, so we choose Europe/Lisbon and are left with

  • 47|Europe/Oslo
  • 4477|Europe/London
  • 3518|Europe/Lisbon

I'm away for a few days so will look at this in detail next week, but yes, returning either a list in list context or a list-ref in scalar context would be sensible.

Not a problem, I'm also going to be away for the next week. I've made a quick stab at returning all the country codes for libphonenumber stubs, I'll get that pushed and link it here.

PR merged, will be in the next release