Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Date Timezone

by kepler (Scribe)
on Jul 15, 2017 at 20:53 UTC ( #1195174=perlquestion: print w/replies, xml ) Need Help??
kepler has asked for the wisdom of the Perl Monks concerning the following question:


I'm having some troubles making a sub function that given an year, month, day and hour and the zone would return the offset in seconds. The general code is this (and works if used in the main routine):

my $tz = DateTime::TimeZone->new( name => $zone ); my $dt = DateTime->new( year => $year_init, month => $month_init, day => $day_init, hour => $hour_init, minute => $minutes_init, second => $seconds_init, nanosecond => 0, ); $offset = $tz->offset_for_datetime($dt); #seconds $offset_days = $offset / 86400; #days

BUT if I place it in a function, let's say sub TZone (), where I receive all the parameters, the program does not give an error but exits (I say this because no more output is done...). If I make a return before the above, it returns what I want (so the function is well formated, except when it calls the offset). Can someone help me out?

Kind regards, Kepler

Replies are listed 'Best First'.
Re: Date Timezone
by soonix (Monsignor) on Jul 16, 2017 at 14:22 UTC
    the program does not give an error but exits (I say this because no more output is done...).
    If this is in a CGI script, error messages would be going to the error log on the server.
    you should specifically look there for a message looking like Too many arguments for main::TimeZone at …, because stevieb's hint here looks spot on:
    Also, you don't need (and unless you know when you should) shouldn't be using prototypes in your sub definition (ie. remove the ()).
Re: Date Timezone
by thanos1983 (Curate) on Jul 16, 2017 at 11:04 UTC

    Hello kepler,

    You have already 83 Writeups on this forum so I think you know what is a Short, Self Contained, Correct (Compilable), Example that fellow monk stevieb is asking you for.

    Just to clarify in case that still is not clear why we all monks asking for that. If you need our assistance, you have to show the minimum effort and create a small script executable that replicates your problem. By doing this you can help us to help you.

    Moving on, are you looking for something like this?

    #!usr/bin/perl use say; use strict; use warnings; use DateTime; use DateTime::TimeZone; sub TimeZone { my ($dt) = @_; my $tz = $dt->time_zone(); my $offset = $tz->offset_for_datetime($dt); return $offset; } my $dt = DateTime->new( year => 1964, month => 10, day => 16, hour => 16, minute => 12, second => 47, nanosecond => 500000000, time_zone => 'Asia/Taipei', ); my $tz = DateTime::TimeZone->new( name => 'America/Chicago' ); my $offset = $tz->offset_for_datetime($dt); say TimeZone($dt); say $offset; __END__ $ perl 28800 -18000

    I used the default parameters as give in DateTime.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Date Timezone
by Anonymous Monk on Jul 15, 2017 at 21:03 UTC
    The general code ... works if used in the main routine ... BUT if I place it in a function

    Show us that then!

      Hi. Sure.

      Here's what I'm trying:

      #!/usr/bin/perl use LWP::Simple; use DateTime; use DateTime::TimeZone; etc etc... sub TimeZone () { (my $year_tz, my $month_init, my $hour_init, my $zone) = @_; $offset_days = 0; $offset = 0; my $minutes_init = 0; my $seconds_init = 0; my $tz = DateTime::TimeZone->new( name => $zone ); my $dt = DateTime->new( year => $year_tz, month => $month_init, day => $day_init, hour => $hour_init, minute => $minutes_init, second => $seconds_init, nanosecond => 0, ); $offset = $tz->offset_for_datetime($dt); $offset_days = $offset / 86400; return $offset_days; }
      As I've said, no error. It just...stops. If I don't call it the entire scripts works.

        being that $offset_days and $offset seem to have a global scope i would look to see if there are side effects in the other code from resetting them, such as loops terminating early or exit getting called

        Hi, stevieb already mentioned this, but just to be clear: If your code is really how you've written it here, your sub is requiring that no arguments be passed to it. The code shown should throw an error if you try to pass it the arguments that you then try to load into @_ ... so are you getting that error? Or have you contrived some way to suppress the error? Or, is this not really the code you are using?

        $ perl -Mstrict -wE 'sub foo{ my $bar = shift; say $bar } foo("baz");' baz $ perl -Mstrict -wE 'sub foo(){ my $bar = shift; say $bar } foo("baz") +;' Too many arguments for main::foo at -e line 1, near ""baz")" Execution of -e aborted due to compilation errors.
        (For more detail, see Prototypes in perlsub.)

        The way forward always starts with a minimal test.

        Please show us a full Short, Self-Contained Correct Example. A full blown script as small as possible that fully shows the problem. What you've shown will just lead to endless guessing. For example, you don't even show us in the etc... where you're actually calling the sub... are you? Also, you don't need (and unless you know when you should) shouldn't be using prototypes in your sub definition (ie. remove the ()).

        Do you have use strict; and use warnings;? huck may be onto something. You are not scoping the return variable within the sub (if it's not declared globally, strict will catch that).

Re: Date Timezone
by sundialsvc4 (Abbot) on Jul 17, 2017 at 04:29 UTC

    When you say that your code “exits, because no more output is done,” then (as soonix has already observed) I would conclude that a runtime exception is being thrown, and that it is killing your script without actually telling you what is going on.

    The Perl5 language does not actually have(!) decent error-catching semantics, although Try::Tiny does actually do a very nice job of patching-up this particular hole in the dike.   If you can’t manage that, then the last few paragraphs of eval will give you the dirty as to how you can actually coax a meaningful failure-message out of an errant block of source code with no further help from anything or anyone.

    Sometimes, after I have recognized that an error is happening “in a particular section of code,” I additionally find that I have to lay down a still-more-thorough trail of bread crumbs.   I usually do this by defining some dummy variable and assigning it different values throughout the block ... then including it in my failure-message when the exception finally gets thrown (and caught).

    Now, having said all of this, your OP description does offer one “smoking gun” prospect:   that your sub TZone() is, in fact, not(!) getting all of its parameters like you suppose that it is!   Therefore, I think that the very first thing that I would do in this case is to modify your routine to log all of its received input-parameters to STDERR.   (“Don’t assume ... don’t assume ...”)

      Please don't bother. The OP has already been helped, and by developers far more competent than you.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1195174]
Front-paged by Corion
[Eily]: s/complete ness/complete mess/ :P
[Eily]: and you can overload "0+" rather than bool, as numification is used instead of stringification in boolean context when available

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (12)
As of 2017-07-27 14:00 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (415 votes). Check out past polls.