Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Timezone converter #125

Merged
merged 5 commits into from

3 participants

@xfix

I've made small timezone converter according to https://duckduckhack.uservoice.com/forums/5168-plugins/suggestions/3066692-timezone-converter. I hope you like it.

@nospampleasemam

Very cool! I've made theses queries countless times myself. I'm taking a look at it right now. Thanks!

@nospampleasemam

I've got it up and running on dylan.duckduckgo.com - check it out! I've merged this goodie into our repository because I think it is already very helpful; we're excited to deploy it. However, I have noticed an irregularity between the parsing of queries with "in" as opposed to "into" triggers. An example of this is https://dylan.duckduckgo.com/?q=10%3A00PM+pst+into+est, which does not trigger with "10:00pm pst to est". Do you have any idea what could be causing this problem?

@xfix

Everything was as intended - in and into were keywords to activate this. But I guess that could be issue, so I've added to to keywords.

@nospampleasemam

Cool! Thanks for getting back to us quickly. One more issue pointed out by @rpicard is preservation of the original query. An example of this is the query "10:00PM PST" which is converted to 24 hour format before display with the new information. We try to keep the original formatting of the users query whenever possible for clarity.

@nospampleasemam nospampleasemam merged commit 19be8a2 into from
@mihugo

One minor suggestion would be to print out the the full name of the time zone being converted.

1pm pst to HST

< convert from ??? ???? Time to Hawaii standard time
< 1:00 P.M. (PST, UTC+8) is 7:00 P.M., 1 day prior (HST, UTC-10).

I put in the ??? ??? above what I wanted was Pacific time (utc-8) but got utc+8 and hence having the full name printed out would possible avoid confusion of similar time zones that can be confused. In this case I think it might actually be giving me the wrong time zone since I'm only aware of one PST time zone and it is UTC-8.
.

@xfix

@mihugo: That definitely would be possible. I like table of timezones in the code, but I guess I could make it way more ugly to do that. I'll make pull request when it'll be ready. As for PST, it would be Philippine Standard Time, but it should be Pacific Standard Time (way more common) - oops.

@xfix xfix referenced this pull request
Merged

PST is -8, not +8. #126

@mihugo

Just confirming that it now gives pacific time instead of Philippine time. You also were very quick. Nice to report a issue and have it fixed so fast. A huge difference from my day job where small fixes like this take weeks of review and panic.
If you do print out the full name of the time zone it might be also nice to put the first line it a plan text format such as

< 1 pm. Pacific Standard time (PST,UTC-8) is 10 am. Hawaii Standard Time (HST, UTC-10)

or perhaps 2 lines

< 1:00 p.m. Pacific Standard time is 10:00 a.m. Hawaii Standard Time
< 1:00 p.m. (PST, UTC+8) is 7:00 p.m., 1 day prior (HST, UTC-10)

I'm having arguments with myself on what looks the best and hence am just throwing out suggestions.

Also to be picky looking around the web it appears that the more common style way of writing the morning and afternoon is to use small characters and not caps but then again there are some style guides that like it the way you have it written. It is fine the way you have it as well. http://www.businesswritingblog.com/business_writing/2009/06/what-is-the-correct-time-am-pm-am-pm-am-pm-.html

Another minor suggestion.
Doing a conversion such as "9 am pst to est" provides an output of 0:00 P.M. Ideally it would be nice to print "noon" and midnight instead of the a.m./p.m. in these cases since the definitions of a.m. and p.m. are not defined for the crossover points. If you really wanted to get fancy you might also recognize an input of noon.

Thanks

@xfix

Also, thanks for reporting issues, but I've feeling it would be more organized if you would use new issues for those :-). This issue was about adding the feature (which was already done). New issues are free, so feel free to open those next time. The bug tracker is really easy to use, just click "New issue" and describe it - it's probably easiest bug tracker I've ever seen.

Also, well, goodies are plugins - as long you don't touch anything that isn't goodie or test for goodie, usually merges are quick.

@nospampleasemam nospampleasemam referenced this pull request from a commit
@nospampleasemam nospampleasemam Merge branch 'timezone-converter' of git://github.com/GlitchMr/zerocl…
…ickinfo-goodies

requested feature of "noon"/"midnight" when using 12-hour clock in duckduckgo/zeroclickinfo-goodies#125.
b48e603
@nospampleasemam

Hi again GlitchMr! We're ready to deploy this plugin. Is there a website, twitter account or anything else you would like us to link to with your attribution? This will appear on duckduckgo.com/goodies.html under Conversions.

@xfix

Well, I don't have Twitter, but I have website - it would be http://glitchmr.github.com/.

@nospampleasemam

This has been deployed to duckduckgo.com :-)

Thanks again!

@xfix

Thanks for deploying, but I'm not mr__shu. Would it be possible to change that to GlitchMr?

@nospampleasemam

Yikes! I'm so sorry. Of course! The change is being deployed right now.

@nospampleasemam

Done! Everything should be correct. Again - I'm sorry about that. I saw your post about writing the plugin! Very cool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 28, 2012
  1. Timezone converter

    GlitchMr authored
  2. Remove Time::Piece that I'm not using.

    GlitchMr authored
  3. Add "TO" as alias for "INTO".

    GlitchMr authored
  4. Use AM/PM style when input uses it.

    GlitchMr authored
This page is out of date. Refresh to see the latest.
Showing with 221 additions and 0 deletions.
  1. +183 −0 lib/DDG/Goodie/TimezoneConverter.pm
  2. +38 −0 t/TimezoneConverter.t
View
183 lib/DDG/Goodie/TimezoneConverter.pm
@@ -0,0 +1,183 @@
+package DDG::Goodie::TimezoneConverter;
+
+use 5.010;
+use strict;
+use warnings;
+use DDG::Goodie;
+use POSIX qw(fmod);
+
+triggers any => qw(in into to);
+
+zci is_cached => 1;
+zci answer_type => 'timezone_converter';
+
+my %timezones = qw(
+ ACDT 10.5 ACST 9.5 ACT 8 ADT -3 AEDT 11 AEST 10
+ AFT 4.5 AKDT -8 AKST -9 AMST 5 AMT 4 ART -3
+ AST -4 AWDT 9 AWST 8 AZOST -1 AZT 4 BDT 8
+ BIOT 6 BIT -12 BOT -4 BRT -3 BST 1 BTT 6
+ CAT 2 CCT 6.5 CDT -5 CEDT 2 CEST 2 CET 1
+ CHADT 13.75 CHAST 12.75 CHOT -8 CHST 10 CHUT 10 CIST -8
+ CIT 8 CKT -10 CLST -3 CLT -4 COST -4 COT -5
+ CST -6 CT 8 CVT -1 CWST 8.75 CXT 7 DAVT 7
+ DDUT 7 DFT 1 EASST -5 EAST -6 EAT 3 ECT -5
+ EDT -4 EEDT 3 EEST 3 EET 2 EGST 0 EGT -1
+ EIT 9 EST -5 FET 3 FJT 12 FKST -3 FKT -4
+ FNT -2 GALT -6 GAMT -9 GET 4 GFT -3 GILT 12
+ GIT -9 GMT 0 GST 4 GYT -4 HADT -9 HAEC 2
+ HAST -10 HKT 8 HMT 5 HOVT 7 HST -10 ICT 7
+ IDT 3 IOT 3 IRDT 8 IRKT 8 IRST 3.5 IST 5.5
+ JST 9 KGT 7 KOST 11 KRAT 7 KST 9 LHST 11
+ LINT 14 MAGT 12 MART -9.5 MAWT 5 MDT -6 MEST 2
+ MET 1 MHT 12 MIST 11 MIT -9.5 MMT 6.5 MSK 4
+ MST -7 MUT 4 MVT 5 MYT 8 NCT 11 NDT -2.5
+ NFT 11.5 NPT 5.75 NST -3.5 NT -3.5 NUT -11.5 NZDT 13
+ NZST 12 OMST 6 ORAT -5 PDT -7 PET -5 PETT 12
+ PGT 10 PHOT 13 PHT 8 PKT 5 PMDT 8 PMST 8
+ PONT 11 PST 8 RET 4 ROTT -3 SAKT 11 SAMT 4
+ SAST 2 SBT 11 SCT 4 SGT 8 SLT 5.5 SRT -3
+ SST -11 SYOT 3 TAHT -10 TFT 5 THA 7 TJT 5
+ TKT 14 TLT 9 TMT 5 TOT 13 TVT 12 UCT 0
+ ULAT 8 UTC 0 UYST -2 UYT -3 UZT 5 VET -4.5
+ VLAT 10 VOLT 4 VOST 6 VUT 11 WAKT 12 WAST 2
+ WAT 1 WEDT 1 WEST 1 WET 0 WST 8 YAKT 9
+ YEKT 5
+);
+
+sub parse_timezone(_) {
+ my $timezone = shift;
+ my ( $name, $modifier, $minutes )
+ = $timezone =~ /\A(\w+)(?:([+-]\d+)(?::(\d\d))?)?\z/;
+
+ # If timezone doesn't exist, skip it
+ return unless defined $timezones{$name};
+
+ # Modifier can be skipped
+ $modifier //= 0;
+
+ # Minutes can be skipped too
+ $minutes //= 0;
+ return $timezones{$name} + $modifier + $minutes / 60;
+}
+
+sub to_time {
+ my ($hours, $american) = @_;
+ my $pm = "";
+ my $seconds = 3600 * fmod $hours, 1 / 60;
+
+ # I'm using floating point numbers. They sometimes don't do what I want.
+ if ( sprintf( '%.5f', $seconds ) == 60 ) {
+ $seconds = 0;
+ }
+ my $minutes
+ = ( $hours - int $hours ) * 60 - sprintf( '%.4f', $seconds ) / 60;
+ my $seconds_format = int $seconds ? ':%02.0f' : "";
+ if ($american) {
+ $pm = ' A.M.';
+ if ($hours >= 12) {
+ $pm = ' P.M.';
+ $hours -= 12;
+ }
+ }
+ sprintf "%i:%02.0f$seconds_format$pm", $hours, $minutes, $seconds;
+}
+
+handle query => sub {
+ my $timezone = qr/(\w+(?:\s*[+-]0*[0-9]{1,5}(?::[0-5][0-9])?)?)?/;
+ my (
+ # Time
+ $hour, $minutes, $seconds, $american, $pm,
+
+ # Timezones
+ $input_timezone, $output_timezone,
+ )
+ = uc =~ m{
+ \A \s*
+ # Time
+ # Hours
+ ([01]?[0-9] | 2[0-3])
+ (?:
+ # Minutes
+ :([0-5] [0-9])
+ (?:
+ # Seconds
+ :([0-5] [0-9])
+ )?
+ )?
+ # Optional spaces between tokens
+ \s*
+ # AM/PM
+ ((?:A|(P))\.?M\.?)?
+ # Spaces between tokens
+ \s* \b
+ # Optional input timezone
+ $timezone
+ # Spaces
+ \s+
+ # in keywords
+ (?: IN (?: TO )? | TO )
+ # Spaces
+ \s+
+ # Output timezone
+ $timezone
+ \s* \z
+ }x or return;
+
+ $pm = $pm ? 12 : 0;
+ $input_timezone //= 'UTC';
+ $minutes //= 0;
+ $seconds //= 0;
+
+ my $modifier = 0;
+ for ( $input_timezone, $output_timezone ) {
+ s/\s+//g;
+ }
+ my $gmt_input_timezone = parse_timezone $input_timezone;
+ my $gmt_output_timezone = parse_timezone $output_timezone;
+ $modifier += $gmt_output_timezone - $gmt_input_timezone;
+ for ( $gmt_input_timezone, $gmt_output_timezone ) {
+ $_ = to_time $_;
+ s/\A\b/+/;
+ s/:00\z//;
+ }
+
+ my $input_time = $hour + $minutes / 60 + $seconds / 3600 + $pm;
+ my $output_time = $input_time + $modifier;
+ for ( $input_time, $output_time ) {
+ my $days = "";
+ if ( $_ < 0 ) {
+ my $s = $_ <= -24 ? 's' : "";
+ $days = sprintf ', %i day%s prior', $_ / -24 + 1, $s;
+
+ # fmod() doesn't do what I want, Perl's % operator doesn't
+ # support floating point numbers. Instead, I will use
+ # lamest hack ever to do things correctly.
+ $_ += int( $_ / -24 + 1 ) * 24;
+ }
+ elsif ( $_ >= 24 ) {
+ my $s = $_ >= 48 ? 's' : "";
+ $days = sprintf ', %i day%s after', $_ / 24, $s;
+ }
+ $_ = fmod $_, 24;
+ $_ = to_time($_, $american) . $days;
+ }
+
+ my ( $input_format, $output_format ) = ('%s, UTC%s') x 2;
+ my @input_timezones = ( $input_timezone, $gmt_input_timezone );
+ my @output_timezones = ( $output_timezone, $gmt_output_timezone );
+
+ # I'm using @timezones because I need list context.
+ if ( !@timezones{ $input_timezone =~ /(\A\w+)/ } ) {
+ $input_format = '%s';
+ pop @input_timezones;
+ }
+ if ( !@timezones{ $output_timezone =~ /(\A\w+)/ } ) {
+ $output_format = '%s';
+ pop @output_timezones;
+ }
+ sprintf "%s ($input_format) is %s ($output_format).",
+ $input_time, @input_timezones,
+ $output_time, @output_timezones;
+};
+
+1;
View
38 t/TimezoneConverter.t
@@ -0,0 +1,38 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use Test::More;
+use DDG::Test::Goodie;
+
+zci answer_type => 'timezone_converter';
+zci is_cached => 1;
+
+ddg_goodie_test(
+ ['DDG::Goodie::TimezoneConverter'],
+ '3:14 in GMT' =>
+ test_zci('3:14 (UTC) is 3:14 (GMT).'),
+ '8:10 A.M. AZOST into CAT' =>
+ test_zci('8:10 A.M. (AZOST, UTC-1) is 11:10 A.M. (CAT, UTC+2).'),
+ '1pm EDT into UTC+2' =>
+ test_zci('1:00 P.M. (EDT, UTC-4) is 7:00 P.M. (UTC+2).'),
+ '1 into UTC -2 ' =>
+ test_zci('1:00 (UTC) is 23:00, 1 day prior (UTC-2).'),
+ ' 1 into UTC-1' =>
+ test_zci('1:00 (UTC) is 0:00 (UTC-1).'),
+ '21 FNT into EET' =>
+ test_zci('21:00 (FNT, UTC-2) is 1:00, 1 day after (EET, UTC+2).'),
+ '23:00:00 InTo UTC+1' =>
+ test_zci('23:00 (UTC) is 0:00, 1 day after (UTC+1).'),
+ '23:00:01 Into UTC+1' =>
+ test_zci('23:00:01 (UTC) is 0:00:01, 1 day after (UTC+1).'),
+ '13:15:00 UTC-0:30 into UTC+0:30' =>
+ test_zci('13:15 (UTC-0:30) is 13:15 (UTC+0:30).'),
+ # ok, this is unlikely to happen without trying to do that
+ '19:42:42 BIT into GMT+100' =>
+ test_zci('19:42:42 (BIT, UTC-12) is 11:42:42, 5 days after (GMT+100).'),
+ '19:42:42 CHADT into GMT-100' =>
+ test_zci('19:42:42 (CHADT, UTC+13:45) is 1:57:42, 4 days prior (GMT-100).'),
+);
+
+done_testing;
Something went wrong with that request. Please try again.