Skip to content
This repository

Timezone converter #125

Merged
merged 5 commits into from over 1 year ago

3 participants

Konrad Borowski Dylan Lloyd mihugo
Konrad Borowski

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

Dylan Lloyd
Collaborator

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

Dylan Lloyd
Collaborator

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?

Konrad Borowski

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.

Dylan Lloyd
Collaborator

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.

Dylan Lloyd nospampleasemam merged commit 19be8a2 into from September 28, 2012
Dylan Lloyd nospampleasemam closed this September 28, 2012
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.
.

Konrad Borowski

@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.

Konrad Borowski xfix referenced this pull request September 29, 2012
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

Konrad Borowski

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.

Dylan Lloyd nospampleasemam referenced this pull request from a commit September 30, 2012
Dylan Lloyd 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
Dylan Lloyd
Collaborator

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.

Konrad Borowski

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

Dylan Lloyd
Collaborator

This has been deployed to duckduckgo.com :-)

Thanks again!

Konrad Borowski

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

Dylan Lloyd
Collaborator

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

Dylan Lloyd
Collaborator

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
This page is out of date. Refresh to see the latest.
183  lib/DDG/Goodie/TimezoneConverter.pm
... ...
@@ -0,0 +1,183 @@
  1
+package DDG::Goodie::TimezoneConverter;
  2
+
  3
+use 5.010;
  4
+use strict;
  5
+use warnings;
  6
+use DDG::Goodie;
  7
+use POSIX qw(fmod);
  8
+
  9
+triggers any => qw(in into to);
  10
+
  11
+zci is_cached   => 1;
  12
+zci answer_type => 'timezone_converter';
  13
+
  14
+my %timezones = qw(
  15
+    ACDT   10.5 ACST    9.5 ACT       8 ADT      -3 AEDT     11 AEST     10
  16
+    AFT     4.5 AKDT     -8 AKST     -9 AMST      5 AMT       4 ART      -3
  17
+    AST      -4 AWDT      9 AWST      8 AZOST    -1 AZT       4 BDT       8
  18
+    BIOT      6 BIT     -12 BOT      -4 BRT      -3 BST       1 BTT       6
  19
+    CAT       2 CCT     6.5 CDT      -5 CEDT      2 CEST      2 CET       1
  20
+    CHADT 13.75 CHAST 12.75 CHOT     -8 CHST     10 CHUT     10 CIST     -8
  21
+    CIT       8 CKT     -10 CLST     -3 CLT      -4 COST     -4 COT      -5
  22
+    CST      -6 CT        8 CVT      -1 CWST   8.75 CXT       7 DAVT      7
  23
+    DDUT      7 DFT       1 EASST    -5 EAST     -6 EAT       3 ECT      -5
  24
+    EDT      -4 EEDT      3 EEST      3 EET       2 EGST      0 EGT      -1
  25
+    EIT       9 EST      -5 FET       3 FJT      12 FKST     -3 FKT      -4
  26
+    FNT      -2 GALT     -6 GAMT     -9 GET       4 GFT      -3 GILT     12
  27
+    GIT      -9 GMT       0 GST       4 GYT      -4 HADT     -9 HAEC      2
  28
+    HAST    -10 HKT       8 HMT       5 HOVT      7 HST     -10 ICT       7
  29
+    IDT       3 IOT       3 IRDT      8 IRKT      8 IRST    3.5 IST     5.5
  30
+    JST       9 KGT       7 KOST     11 KRAT      7 KST       9 LHST     11
  31
+    LINT     14 MAGT     12 MART   -9.5 MAWT      5 MDT      -6 MEST      2
  32
+    MET       1 MHT      12 MIST     11 MIT    -9.5 MMT     6.5 MSK       4
  33
+    MST      -7 MUT       4 MVT       5 MYT       8 NCT      11 NDT    -2.5
  34
+    NFT    11.5 NPT    5.75 NST    -3.5 NT     -3.5 NUT   -11.5 NZDT     13
  35
+    NZST     12 OMST      6 ORAT     -5 PDT      -7 PET      -5 PETT     12
  36
+    PGT      10 PHOT     13 PHT       8 PKT       5 PMDT      8 PMST      8
  37
+    PONT     11 PST       8 RET       4 ROTT     -3 SAKT     11 SAMT      4
  38
+    SAST      2 SBT      11 SCT       4 SGT       8 SLT     5.5 SRT      -3
  39
+    SST     -11 SYOT      3 TAHT    -10 TFT       5 THA       7 TJT       5
  40
+    TKT      14 TLT       9 TMT       5 TOT      13 TVT      12 UCT       0
  41
+    ULAT      8 UTC       0 UYST     -2 UYT      -3 UZT       5 VET    -4.5
  42
+    VLAT     10 VOLT      4 VOST      6 VUT      11 WAKT     12 WAST      2
  43
+    WAT       1 WEDT      1 WEST      1 WET       0 WST       8 YAKT      9
  44
+    YEKT      5
  45
+);
  46
+
  47
+sub parse_timezone(_) {
  48
+    my $timezone = shift;
  49
+    my ( $name, $modifier, $minutes )
  50
+        = $timezone =~ /\A(\w+)(?:([+-]\d+)(?::(\d\d))?)?\z/;
  51
+
  52
+    # If timezone doesn't exist, skip it
  53
+    return unless defined $timezones{$name};
  54
+
  55
+    # Modifier can be skipped
  56
+    $modifier //= 0;
  57
+
  58
+    # Minutes can be skipped too
  59
+    $minutes //= 0;
  60
+    return $timezones{$name} + $modifier + $minutes / 60;
  61
+}
  62
+
  63
+sub to_time {
  64
+    my ($hours, $american) = @_;
  65
+    my $pm = "";
  66
+    my $seconds = 3600 * fmod $hours, 1 / 60;
  67
+
  68
+    # I'm using floating point numbers. They sometimes don't do what I want.
  69
+    if ( sprintf( '%.5f', $seconds ) == 60 ) {
  70
+        $seconds = 0;
  71
+    }
  72
+    my $minutes
  73
+        = ( $hours - int $hours ) * 60 - sprintf( '%.4f', $seconds ) / 60;
  74
+    my $seconds_format = int $seconds ? ':%02.0f' : "";
  75
+    if ($american) {
  76
+        $pm = ' A.M.';
  77
+        if ($hours >= 12) {
  78
+            $pm = ' P.M.';
  79
+            $hours -= 12;
  80
+        }
  81
+    }
  82
+    sprintf "%i:%02.0f$seconds_format$pm", $hours, $minutes, $seconds;
  83
+}
  84
+
  85
+handle query => sub {
  86
+    my $timezone = qr/(\w+(?:\s*[+-]0*[0-9]{1,5}(?::[0-5][0-9])?)?)?/;
  87
+    my (
  88
+        # Time
  89
+        $hour, $minutes, $seconds, $american, $pm,
  90
+
  91
+        # Timezones
  92
+        $input_timezone, $output_timezone,
  93
+        )
  94
+        = uc =~ m{
  95
+        \A \s*
  96
+        # Time
  97
+          # Hours
  98
+          ([01]?[0-9] | 2[0-3])
  99
+          (?:
  100
+            # Minutes
  101
+            :([0-5] [0-9])
  102
+            (?:
  103
+              # Seconds
  104
+              :([0-5] [0-9])
  105
+            )?
  106
+          )?
  107
+          # Optional spaces between tokens
  108
+          \s*
  109
+          # AM/PM
  110
+          ((?:A|(P))\.?M\.?)?
  111
+        # Spaces between tokens
  112
+        \s* \b
  113
+        # Optional input timezone
  114
+        $timezone
  115
+        # Spaces
  116
+        \s+
  117
+        # in keywords
  118
+        (?: IN (?: TO )? | TO )
  119
+        # Spaces
  120
+        \s+
  121
+        # Output timezone
  122
+        $timezone
  123
+        \s* \z
  124
+    }x or return;
  125
+
  126
+    $pm = $pm ? 12 : 0;
  127
+    $input_timezone //= 'UTC';
  128
+    $minutes        //= 0;
  129
+    $seconds        //= 0;
  130
+
  131
+    my $modifier = 0;
  132
+    for ( $input_timezone, $output_timezone ) {
  133
+        s/\s+//g;
  134
+    }
  135
+    my $gmt_input_timezone  = parse_timezone $input_timezone;
  136
+    my $gmt_output_timezone = parse_timezone $output_timezone;
  137
+    $modifier += $gmt_output_timezone - $gmt_input_timezone;
  138
+    for ( $gmt_input_timezone, $gmt_output_timezone ) {
  139
+        $_ = to_time $_;
  140
+        s/\A\b/+/;
  141
+        s/:00\z//;
  142
+    }
  143
+
  144
+    my $input_time  = $hour + $minutes / 60 + $seconds / 3600 + $pm;
  145
+    my $output_time = $input_time + $modifier;
  146
+    for ( $input_time, $output_time ) {
  147
+        my $days = "";
  148
+        if ( $_ < 0 ) {
  149
+            my $s = $_ <= -24 ? 's' : "";
  150
+            $days = sprintf ', %i day%s prior', $_ / -24 + 1, $s;
  151
+
  152
+            # fmod() doesn't do what I want, Perl's % operator doesn't
  153
+            # support floating point numbers. Instead, I will use
  154
+            # lamest hack ever to do things correctly.
  155
+            $_ += int( $_ / -24 + 1 ) * 24;
  156
+        }
  157
+        elsif ( $_ >= 24 ) {
  158
+            my $s = $_ >= 48 ? 's' : "";
  159
+            $days = sprintf ', %i day%s after', $_ / 24, $s;
  160
+        }
  161
+        $_ = fmod $_, 24;
  162
+        $_ = to_time($_, $american) . $days;
  163
+    }
  164
+
  165
+    my ( $input_format, $output_format ) = ('%s, UTC%s') x 2;
  166
+    my @input_timezones  = ( $input_timezone,  $gmt_input_timezone );
  167
+    my @output_timezones = ( $output_timezone, $gmt_output_timezone );
  168
+
  169
+    # I'm using @timezones because I need list context.
  170
+    if ( !@timezones{ $input_timezone =~ /(\A\w+)/ } ) {
  171
+        $input_format = '%s';
  172
+        pop @input_timezones;
  173
+    }
  174
+    if ( !@timezones{ $output_timezone =~ /(\A\w+)/ } ) {
  175
+        $output_format = '%s';
  176
+        pop @output_timezones;
  177
+    }
  178
+    sprintf "%s ($input_format) is %s ($output_format).",
  179
+        $input_time,  @input_timezones,
  180
+        $output_time, @output_timezones;
  181
+};
  182
+
  183
+1;
38  t/TimezoneConverter.t
... ...
@@ -0,0 +1,38 @@
  1
+#!/usr/bin/env perl
  2
+
  3
+use strict;
  4
+use warnings;
  5
+use Test::More;
  6
+use DDG::Test::Goodie;
  7
+
  8
+zci answer_type => 'timezone_converter';
  9
+zci is_cached => 1;
  10
+
  11
+ddg_goodie_test(
  12
+    ['DDG::Goodie::TimezoneConverter'],
  13
+    '3:14 in GMT' =>
  14
+        test_zci('3:14 (UTC) is 3:14 (GMT).'),
  15
+    '8:10 A.M. AZOST into CAT' =>
  16
+        test_zci('8:10 A.M. (AZOST, UTC-1) is 11:10 A.M. (CAT, UTC+2).'),
  17
+    '1pm EDT into UTC+2' =>
  18
+        test_zci('1:00 P.M. (EDT, UTC-4) is 7:00 P.M. (UTC+2).'),
  19
+    '1 into UTC -2 ' =>
  20
+        test_zci('1:00 (UTC) is 23:00, 1 day prior (UTC-2).'),
  21
+    ' 1 into UTC-1' =>
  22
+        test_zci('1:00 (UTC) is 0:00 (UTC-1).'),
  23
+    '21 FNT into EET' =>
  24
+        test_zci('21:00 (FNT, UTC-2) is 1:00, 1 day after (EET, UTC+2).'),
  25
+    '23:00:00  InTo  UTC+1' =>
  26
+        test_zci('23:00 (UTC) is 0:00, 1 day after (UTC+1).'),
  27
+    '23:00:01  Into    UTC+1' =>
  28
+        test_zci('23:00:01 (UTC) is 0:00:01, 1 day after (UTC+1).'),
  29
+    '13:15:00 UTC-0:30 into UTC+0:30' =>
  30
+        test_zci('13:15 (UTC-0:30) is 13:15 (UTC+0:30).'),
  31
+    # ok, this is unlikely to happen without trying to do that
  32
+    '19:42:42 BIT into GMT+100' =>
  33
+        test_zci('19:42:42 (BIT, UTC-12) is 11:42:42, 5 days after (GMT+100).'),
  34
+    '19:42:42 CHADT into GMT-100' =>
  35
+        test_zci('19:42:42 (CHADT, UTC+13:45) is 1:57:42, 4 days prior (GMT-100).'),   
  36
+);
  37
+
  38
+done_testing;
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.