App-TimeTracker

 view release on metacpan or  search on metacpan

Build.PL  view on Meta::CPAN

    "Thomas Klausner <domm\@plix.at>"
  ],
  "dist_name" => "App-TimeTracker",
  "dist_version" => "3.010",
  "license" => "perl",
  "module_name" => "App::TimeTracker",
  "recursive_test_files" => 1,
  "requires" => {
    "Carp" => 0,
    "Data::Dumper" => 0,
    "DateTime" => 0,
    "DateTime::Format::Duration" => 0,
    "DateTime::Format::ISO8601" => 0,
    "Exporter" => 0,
    "File::Copy" => 0,
    "File::Find::Rule" => 0,
    "File::HomeDir" => 0,
    "Hash::Merge" => 0,
    "JSON::XS" => 0,
    "Moose" => 0,
    "Moose::Role" => 0,
    "Moose::Util::TypeConstraints" => 0,
    "MooseX::Getopt" => 0,

Changes  view on Meta::CPAN

    - squash a warning (cpan-rt75266) (Thomas Klausner)
    - fix tag sorting (Jozef Kutej)
    - set tracker script STDOUT to utf8 (Jozef Kutej)
    - add description to the detail report (Jozef Kutej)
    - Switch to Digest::SHA (in core since 5.9.3) to reduce external
      deps (Roland Lammel)


2.017   2012-01-12T22:59:32+0100
    - finally fixed rt.cpan.org #73859:
      During DateTime coercion for --at new DateTime objects
      were initiated without setting time_zone => 'local'
      That's added now (and tested), so hopefully the bug IS squashed
    - new command: version
      prints out the current version
    - add suggestion for better --at if stop<start
      (suggested by Ruslan Zakirov)


2.016   2012-01-10T23:08:20+0100
    - fixed rt.cpan.org #73859 reported by Ruslan Zakirov:

Changes  view on Meta::CPAN

      make syncing via git et.al. easier


0.08	2008-04-04
    - added cmd "report"
    - added --this and --last to "worked"
    - "worked" now works with tags
    - added --from and --to to "worked"
    - added --svn to "stop"
    - added some docs
    - added missing dependency on DateTime::Format::Strptime


0.07    2008-01-23
    - added docs
    - fixed bad default filepath


0.06    2008-01-22
    - renamed to App::TimeTracker
    - first release to CPAN

META.json  view on Meta::CPAN

      },
      "configure" : {
         "requires" : {
            "Module::Build" : "0.28"
         }
      },
      "runtime" : {
         "requires" : {
            "Carp" : "0",
            "Data::Dumper" : "0",
            "DateTime" : "0",
            "DateTime::Format::Duration" : "0",
            "DateTime::Format::ISO8601" : "0",
            "Exporter" : "0",
            "File::Copy" : "0",
            "File::Find::Rule" : "0",
            "File::HomeDir" : "0",
            "Hash::Merge" : "0",
            "JSON::XS" : "0",
            "Moose" : "0",
            "Moose::Role" : "0",
            "Moose::Util::TypeConstraints" : "0",
            "MooseX::Getopt" : "0",

cpanfile  view on Meta::CPAN

# This file is generated by Dist::Zilla::Plugin::CPANFile v6.024
# Do not edit this file directly. To change prereqs, edit the `dist.ini` file.

requires "Carp" => "0";
requires "Data::Dumper" => "0";
requires "DateTime" => "0";
requires "DateTime::Format::Duration" => "0";
requires "DateTime::Format::ISO8601" => "0";
requires "Exporter" => "0";
requires "File::Copy" => "0";
requires "File::Find::Rule" => "0";
requires "File::HomeDir" => "0";
requires "Hash::Merge" => "0";
requires "JSON::XS" => "0";
requires "Moose" => "0";
requires "Moose::Role" => "0";
requires "Moose::Util::TypeConstraints" => "0";
requires "MooseX::Getopt" => "0";

helper/convert_2_003_to_2_004.pl  view on Meta::CPAN

#!/env perl

use strict;
use warnings;
use 5.010;

use File::Find::Rule;
use Data::Dumper;
use App::TimeTracker::Data::Task;
use App::TimeTracker::Proto;
use DateTime;
use Path::Class;
use Try::Tiny;
use JSON::XS;
use Path::Class;

$|=1;
my $app = App::TimeTracker::Proto->new;
my @files = File::Find::Rule->file()->name(qr/\.trc$/)
    ->in( $app->home );

helper/convert_legacy_data_to_json.pl  view on Meta::CPAN

#!/env perl

use strict;
use warnings;
use 5.010;

use File::Find::Rule;
use Data::Dumper;
use App::TimeTracker::Data::Task;
use DateTime;
use Path::Class;
use Try::Tiny;

$|=1;
my ($in, $out) = @ARGV;
die "please specify dir containing old-style files" unless -d $in;
die "please specify dir to contain new-style files" unless -d $out;
$out = Path::Class::dir($out);

my @files = File::Find::Rule->file()->name(qr/\.(done|current)$/)

helper/convert_legacy_data_to_json.pl  view on Meta::CPAN

        }

        my @tags;
        if ($data{tags}) {
            foreach (split(/\s+/,$data{tags})) {
                push(@tags,$_);
            }
        }

        my $task = App::TimeTracker::Data::Task->new({
                start=>DateTime->from_epoch(epoch=>$data{start}, time_zone=>'local'),
                stop=>DateTime->from_epoch(epoch=>$data{stop}, time_zone=>'local'),
                project=>$data{project},
                tags=>\@tags,
        });

        $task->save($out);
        print '.';
    }
    catch {
        die "An error occurred converting $old";
    }

lib/App/TimeTracker.pm  view on Meta::CPAN

package App::TimeTracker;

# ABSTRACT: time tracking for impatient and lazy command line lovers
our $VERSION = '3.010'; # VERSION

use strict;
use warnings;
use 5.010;

use App::TimeTracker::Data::Task;
use DateTime;
use Moose;
use Moose::Util::TypeConstraints;
use Path::Class qw();
use Path::Class::Iterator;
use MooseX::Storage::Format::JSONpm;
use JSON::XS;

our $HOUR_RE   = qr/(?<hour>[012]?\d)/;
our $MINUTE_RE = qr/(?<minute>[0-5]?\d)/;
our $DAY_RE    = qr/(?<day>[0123]?\d)/;
our $MONTH_RE  = qr/(?<month>[01]?\d)/;
our $YEAR_RE   = qr/(?<year>2\d{3})/;

with qw(
    MooseX::Getopt
);

subtype 'TT::DateTime' => as class_type('DateTime');
subtype 'TT::RT'       => as 'Int';
subtype 'TT::Duration' => as enum( [qw(day week month year)] );

coerce 'TT::RT' => from 'Str' => via {
    my $raw = $_;
    $raw =~ s/\D//g;
    return $raw;
};

coerce 'TT::DateTime' => from 'Str' => via {
    my $raw = $_;
    my $dt  = DateTime->now;
    $dt->set_time_zone('local');
    $dt->set( second => 0 );

    if ($raw) {
        if ( $raw =~ /^ $HOUR_RE : $MINUTE_RE $/x ) {    # "13:42"
            $dt->set( hour => $+{hour}, minute => $+{minute} );
        }
        elsif ( $raw =~ /^ $YEAR_RE [-.]? $MONTH_RE [-.]? $DAY_RE $/x )
        {                                                # "2010-02-26"
            $dt->set( year => $+{year}, month => $+{month}, day => $+{day} );

lib/App/TimeTracker.pm  view on Meta::CPAN

                hour   => $+{hour},
                minute => $+{minute} );
        }
        else {
            confess "Invalid date format '$raw'";
        }
    }
    return $dt;
};

MooseX::Getopt::OptionTypeMap->add_option_type_to_map( 'TT::DateTime' => '=s',
);
MooseX::Getopt::OptionTypeMap->add_option_type_to_map( 'TT::RT' => '=i', );

no Moose::Util::TypeConstraints;

has 'home' => (
    is       => 'ro',
    isa      => 'Path::Class::Dir',
    traits   => ['NoGetopt'],
    required => 1,

lib/App/TimeTracker.pm  view on Meta::CPAN

    my $self = shift;
    my $command = 'cmd_' . ( $self->extra_argv->[0] || 'missing' );

    $self->cmd_commands()
        unless $self->can($command);
    $self->_current_command($command);
    $self->$command;
}

sub now {
    my $dt = DateTime->now();
    $dt->set_time_zone('local');
    return $dt;
}

sub beautify_seconds {
    my ( $self, $s ) = @_;
    return '0' unless $s;
    my ( $m, $h ) = ( 0, 0 );

    if ( $s >= 60 ) {

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN

use 5.010;

use Moose::Role;
use Moose::Util::TypeConstraints;
use App::TimeTracker::Utils qw(now pretty_date error_message);
use App::TimeTracker::Constants qw(MISSING_PROJECT_HELP_MSG);
use File::Copy qw(move);
use File::Find::Rule;
use Data::Dumper;
use Text::Table;
use DateTime;

sub cmd_start {
    my $self = shift;

    unless ( $self->has_current_project ) {
        error_message( MISSING_PROJECT_HELP_MSG );
        exit;
    }
    $self->cmd_stop('no_exit');

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN

    if ($parent) {
        unshift( @$ancestors, $parent );
        $self->_get_ancestors( $report, $projects, $parent, $ancestors );
    }
}

sub _first_day_of_week {
    my ( $self, $year, $week ) = @_;

    # Week 1 is defined as the one containing January 4:
    return DateTime->new( year => $year, month => 1, day => 4 )
        ->add( weeks => ( $week - 1 ) )->truncate( to => 'week' );
}

sub _print_report_tree {
    my ( $self, $report, $projects, $project, $padding, $tagpadding ) = @_;
    my $data = $report->{$project};

    my $sum = 0;
    $sum += $data->{'_total'} if $data->{'_total'};
    $sum += $data->{'_kids'}  if $data->{'_kids'};

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN

            say "\t$command";
        }
    }
    exit;
}

sub _load_attribs_worked {
    my ( $class, $meta ) = @_;
    $meta->add_attribute(
        'from' => {
            isa        => 'TT::DateTime',
            is         => 'ro',
            coerce     => 1,
            lazy_build => 1,

            #cmd_aliases  => [qw/start/],
            documentation => 'Beginning of time period to report',
        }
    );
    $meta->add_attribute(
        'to' => {
            isa    => 'TT::DateTime',
            is     => 'ro',
            coerce => 1,

            #cmd_aliases  => [qw/end/],
            lazy_build    => 1,
            documentation => 'End of time period to report',
        }
    );
    $meta->add_attribute(
        'this' => {

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN

            default       => 'project',
            documentation => 'Genereta Report by week or project.'
        }
    );
}

sub _load_attribs_start {
    my ( $class, $meta ) = @_;
    $meta->add_attribute(
        'at' => {
            isa           => 'TT::DateTime',
            is            => 'ro',
            coerce        => 1,
            documentation => 'Start at',
        }
    );
    $meta->add_attribute(
        'project' => {
            isa           => 'Str',
            is            => 'ro',
            documentation => 'Project name',

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN


=head2 start

    ~/perl/Your-Project$ tracker start
    Started working on Your-Project at 23:44:19

Start tracking the current project now. Automatically stop the previous task, if there was one.

=head3 Options:

=head4 --at TT::DateTime

    ~/perl/Your-Project$ tracker start --at 12:42
    ~/perl/Your-Project$ tracker start --at '2011-02-26 12:42'

Start at the specified time/datetime instead of now. If only a time is
provided, the day defaults to today. See L<TT::DateTime> in L<App::TimeTracker>.

=head4 --project SomeProject

  ~/perl/Your-Project$ tracker start --project SomeProject

Use the specified project instead of the one determined by the current
working directory.

=head4 --description 'some prosa'

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN


=head2 stop

    ~/perl/Your-Project$ tracker stop
    Worked 00:20:50 on Your-Project

Stop tracking the current project now.

=head3 Options

=head4 --at TT::DateTime

Stop at the specified time/datetime instead of now.

=head2 continue

    ~/perl/Your-Project$ tracker continue

Continue working on the previous task after a break.

Example:

lib/App/TimeTracker/Command/Core.pm  view on Meta::CPAN


=head2 worked

    ~/perl/Your-Project$ tracker worked [SPAN]

Report the total time worked in the given time span, maybe limited to
some projects.

=head3 Options:

=head4 --from TT::DateTime [REQUIRED (or use --this/--last)]

Begin of reporting interval, defaults to first day of current month.

=head4 --to TT::DateTime [REQUIRED (or use --this/--last)]

End of reporting interval, default to DateTime->now.

=head4 --this [day, week, month, year]

Automatically set C<--from> and C<--to> to the calculated values

    ~/perl/Your-Project$ tracker worked --this week
    17:01:50

=head4 --last [day, week, month, year]

lib/App/TimeTracker/Data/Task.pm  view on Meta::CPAN


# ABSTRACT: App::TimeTracker Task storage
our $VERSION = '3.010'; # VERSION

use 5.010;

use Moose;
use App::TimeTracker::Utils qw(now);
use namespace::autoclean;
use App::TimeTracker;
use DateTime::Format::ISO8601;
use DateTime::Format::Duration;
use User::pwent;
use MooseX::Storage;

with Storage(
    format => [ JSONpm => { json_opts => { pretty => 1, canonical => 1 } } ],
    io     => "File",
);

MooseX::Storage::Engine->add_custom_type_handler(
    'DateTime' => (
        expand   => sub { DateTime::Format::ISO8601->parse_datetime(shift) },
        collapse => sub { (shift)->iso8601 } ) );
my $dtf_dur = DateTime::Format::Duration->new( pattern => '%H:%M:%S',
    normalise => 1 );
my $dtf_sec = DateTime::Format::Duration->new( pattern => '%s' );

has 'start' => (
    isa      => 'DateTime',
    is       => 'ro',
    required => 1,
    default  => sub { now() } );
has 'stop' => (
    isa     => 'DateTime',
    is      => 'rw',
    trigger => \&_calc_duration,
);
has 'seconds' => (
    isa        => 'Maybe[Int]',
    is         => 'rw',
    lazy_build => 1,
);

sub _build_seconds {

lib/App/TimeTracker/Utils.pm  view on Meta::CPAN


    print color $color;
    print $string;
    say color 'reset';
}

sub pretty_date {
    my ($date) = @_;

    unless ( blessed $date
        && $date->isa('DateTime') )
    {
        return $date;
    }
    else {
        my $now = now();
        my $yesterday = now()->subtract( days => 1 );
        if ( $date->dmy eq $now->dmy ) {
            return $date->hms(':');
        }
        elsif ( $date->dmy eq $yesterday->dmy ) {
            return 'yesterday ' . $date->hms(':');
        }
        else {
            return $date->dmy('.') . ' ' . $date->hms(':');
        }
    }
}

sub now {
    my $dt = DateTime->now();
    $dt->set_time_zone('local');
    return $dt;
}
1;

__END__

=pod

=encoding UTF-8

t/Command/core.t  view on Meta::CPAN

use App::TimeTracker::Proto;
local $ENV{TZ} = 'UTC';

my $tmp  = testlib::Fixtures::setup_tempdir;
my $home = $tmp->subdir('.TimeTracker');
$tmp->subdir('some_project')->mkpath;
$tmp->subdir('other_project')->mkpath;
$tmp->subdir('project_name_auto')->mkpath;
$tmp->subdir('project_name_custom')->mkpath;
my $p   = App::TimeTracker::Proto->new( home => $home );
my $now = DateTime->now;
$now->set_time_zone('local');
my $basetf      = $now->ymd('') . '-';
my $tracker_dir = $home->subdir( $now->year, sprintf( "%02d", $now->month ) );

{    # init
    @ARGV = ('init');
    my $class = $p->setup_class( {} );

    file_exists_ok( $home->file('projects.json') );
    file_exists_ok( $home->file('tracker.json') );

t/Command/rt_73859_daychange.t  view on Meta::CPAN

use 5.010;
use strict;
use warnings;
use lib qw(t);

use Test::MockTime qw();    # this needs to be loaded before DateTime
                            # http://www.nntp.perl.org/group/perl.datetime/2008/08/msg7043.html
use Test::Most;
use Test::Trap;
use Test::File;
use testlib::FakeHomeDir;
use App::TimeTracker::Proto;
use DateTime;
local $ENV{TZ} = 'UTC';

my $tmp    = testlib::Fixtures::setup_tempdir;
my $home   = $tmp->subdir('.TimeTracker');
my $prjdir = $tmp->subdir('rt73859');
$home->mkpath;
$prjdir->mkpath;
$home->file('projects.json')
    ->spew( iomode => '>:encoding(UTF-8)', '{"rt73859":"' . $prjdir . '"}' . "\n" );
$prjdir->file('.tracker.json')->spew( iomode => '>:encoding(UTF-8)', '{}' . "\n" );

t/Command/rt_73859_daychange.t  view on Meta::CPAN

my $p = App::TimeTracker::Proto->new( home => $home, project => 'rt73859' );
$p->load_config( $home, 'rt73859' );
my $tracker_dir = $home->subdir( '2012', '01' );
my $c           = { project => 'rt73859' };

# test what was reported, but it works
diag("Test initial bug report");

{    # start
    my $test_date =
        DateTime->new( year => 2012, month => 1, day => 9, hour => 21, time_zone => 'local' );
    Test::MockTime::set_fixed_time( $test_date->epoch );

    @ARGV = ('start');
    my $class = $p->setup_class($c);
    my $t     = $class->name->new(
        home             => $home,
        config           => $c,
        _current_project => 'rt73859',
        at               => '23:30'
    );
    trap { $t->cmd_start };
    is( $trap->stdout, "Started working on rt73859 at 23:30:00\n", 'start: output' );
    file_not_empty_ok( $tracker_dir->file('20120109-233000_rt73859.trc'), 'tracker file exists' );
}

{    # stop
    my $test_date = DateTime->new(
        year      => 2012,
        month     => 1,
        day       => 10,
        hour      => '00',
        minute    => 3,
        time_zone => 'local'
    );
    Test::MockTime::set_fixed_time( $test_date->epoch );

    @ARGV = ('stop');

t/Command/rt_73859_daychange.t  view on Meta::CPAN

    is( $task->seconds,  60 * 60,    'task: seconds' );
    is( $task->duration, '01:00:00', 'task: duration' );
}

# ah, I assume there is a different bug:
# if you issue 'tracker stop --at 00:10' but it is 23:59, the stop-time will be set for the current day, i.e. way before the start time
# solution do not allow to set stop times that are before the start time.
diag("Test de facto bug");

{    # start
    my $test_date = DateTime->new(
        year      => 2012,
        month     => 1,
        day       => 8,
        hour      => 23,
        minute    => 30,
        time_zone => 'local'
    );
    Test::MockTime::set_fixed_time( $test_date->epoch );

    @ARGV = ('start');
    my $class = $p->setup_class($c);
    my $t     = $class->name->new( home => $home, config => $c, _current_project => 'rt73859' );
    trap { $t->cmd_start };

    is( $trap->stdout, "Started working on rt73859 at 23:30:00\n", 'start: output' );
    file_not_empty_ok( $tracker_dir->file('20120108-233000_rt73859.trc'), 'tracker file exists' );
}

{    # stop
    my $test_date = DateTime->new(
        year      => 2012,
        month     => 1,
        day       => 8,
        hour      => 23,
        minute    => 45,
        time_zone => 'local'
    );
    Test::MockTime::set_fixed_time( $test_date->epoch );

    @ARGV = ('stop');

t/Command/rt_73859_daychange.t  view on Meta::CPAN

    trap { $t->cmd_stop };

    like( $trap->stdout, qr/This makes no sense/, 'stop: aborted output' );
    my $task = App::TimeTracker::Data::Task->load(
        $tracker_dir->file('20120108-233000_rt73859.trc')->stringify );
    is( $task->stop, undef, 'task: no stop time' );
    file_not_empty_ok( $home->file('current'), '"current" file still exists' );
}

{    # stop again, with long --at
    my $test_date = DateTime->new(
        year      => 2012,
        month     => 1,
        day       => 8,
        hour      => 23,
        minute    => 45,
        time_zone => 'local'
    );
    Test::MockTime::set_fixed_time( $test_date->epoch );

    @ARGV = ('stop');

t/Task/helpers.t  view on Meta::CPAN

use 5.010;
use strict;
use warnings;
use lib 't';

use Test::Most;
use DateTime;

use App::TimeTracker::Data::Task;

{    # _calc_duration, rounded_minutes
    my $task = App::TimeTracker::Data::Task->new(
        {   project => 'test',
            start   => DateTime->new(
                year   => 2010,
                month  => 2,
                day    => 26,
                hour   => 10,
                minute => 5,
                second => 42
            ),
            description =>
                'Some Test Task described in a very long sentence that will be probably be shortend',
        }
    );
    my $stop = DateTime->new(
        year   => 2010,
        month  => 2,
        day    => 26,
        hour   => 12,
        minute => 25,
        second => 13
    );
    $task->_calc_duration($stop);
    is( $task->seconds,         '8371',     '_calc_duration: seconds' );
    is( $task->duration,        '02:19:31', '_calc_duration: duration' );

t/Task/helpers.t  view on Meta::CPAN

    is( $task->seconds,         '11971',    '_calc_duration: seconds' );
    is( $task->duration,        '03:19:31', '_calc_duration: duration' );
    is( $task->rounded_minutes, 200,        'rounded_minutes' );
    is( $task->description_short, 'Some Test Task described in a very long sentence...',
        'description_short' );
}

{    # rounded_minutes
    my $task = App::TimeTracker::Data::Task->new(
        {   project => 'test',
            start   => DateTime->new(
                year   => 2010,
                month  => 2,
                day    => 26,
                hour   => 10,
                minute => 5,
                second => 0
            ),
            description => 'Worked exactly 15 minutes',
        }
    );
    my $stop = DateTime->new(
        year   => 2010,
        month  => 2,
        day    => 26,
        hour   => 10,
        minute => 20,
        second => 0
    );
    $task->_calc_duration($stop);
    is( $task->duration,        '00:15:00', 'task duration is 15 minutes' );
    is( $task->rounded_minutes, 15,         'rounded_minutes' );

t/Task/start.t  view on Meta::CPAN

use testlib::Fixtures;
use App::TimeTracker::Data::Task;
local $ENV{TZ} = 'UTC';

my $capture = IO::Capture::Stdout->new();
my $tmp     = testlib::Fixtures::setup_tempdir;

{
    my $task = App::TimeTracker::Data::Task->new(
        {   project => 'test',
            start   => DateTime->new(
                year   => 2010,
                month  => 2,
                day    => 26,
                hour   => 10,
                minute => 5,
                second => 42
            ),
        }
    );

t/Task/storage_location.t  view on Meta::CPAN

use 5.010;
use strict;
use warnings;
use lib 't';

use Test::Most;
use testlib::Fixtures;
use DateTime;
use App::TimeTracker::Data::Task;

my $tmp = testlib::Fixtures::setup_tempdir;

{
    my $task = App::TimeTracker::Data::Task->new(
        {   project => 'test',
            start   => DateTime->new(
                year   => 2010,
                month  => 2,
                day    => 26,
                hour   => 10,
                minute => 5,
                second => 42
            ),
        }
    );

t/TimeTracker/datetime_coerce.t  view on Meta::CPAN


use Test::Most;
use App::TimeTracker;
use testlib::Fixtures;
my $tmp = testlib::Fixtures::setup_tempdir;

package ThisTest;
use Moose;
extends 'App::TimeTracker';
has 'dt' => (
    isa    => 'TT::DateTime',
    is     => 'ro',
    coerce => 1,
);

package main;

local $ENV{TZ} = 'UTC';

my $now = DateTime->now;
$now->set_time_zone('local');
my $date = DateTime->new( year => 2012, month => 2, day => 26, time_zone => 'UTC' );

foreach my $test (
    [ '12:34',            $now->clone->set( hour => 12, minute => 34, second => 0 ) ],
    [ '0:1',              $now->clone->set( hour => 0,  minute => 1,  second => 0 ) ],
    [ '2012-02-26',       $date->clone ],
    [ '2012-02-26 12:34', $date->clone->set( hour => 12, minute => 34, second => 0 ) ],

    # for our crazy American friends...
    [ '26-02-2012',       $date->clone ],
    [ '26-02-2012 12:34', $date->clone->set( hour => 12, minute => 34, second => 0 ) ],

t/TimeTracker/find_task_files.t  view on Meta::CPAN

use 5.010;
use strict;
use warnings;
use lib 't';

use Test::Most;
use testlib::Fixtures;
use DateTime;
use App::TimeTracker;
local $ENV{TZ} = 'UTC';

my $tmp = testlib::Fixtures->setup_2011_05;
my $t   = App::TimeTracker->new( home => $tmp, config => {} );

{
    my @files = $t->find_task_files(
        {   from => DateTime->new( year => '2011', month => 5, day => 20 ),
            to   => DateTime->new( year => '2011', month => 5, day => 25 ),
        }
    );
    is( scalar @files, 6, 'got 6 files' );
    is( $files[0],     $tmp->file( '2011', '05', '20110520-093423_oe1_orf_at.trc' ), 'first file' );
    is( $files[5], $tmp->file( '2011', '05', '20110525-224324_App_TimeTracker.trc' ), 'last file' );
}

{
    my @files = $t->find_task_files( { projects => ['TimeTracker'], } );
    is( scalar @files,                              7, 'got 7 files' );
    is( ( scalar grep {/App_TimeTracker/} @files ), 7, 'all match project' );
}

{
    my @files = $t->find_task_files(
        {   from     => DateTime->new( year => '2011', month => 5, day => 1 ),
            projects => ['oe1'],
        }
    );
    is( scalar @files, 16, 'got 16 files' );
}

done_testing();

t/TimeTracker/helpers.t  view on Meta::CPAN

use 5.010;
use strict;
use warnings;
use lib 't';

use Test::Most;
use testlib::Fixtures;
use DateTime;
use App::TimeTracker;
my $tmp = testlib::Fixtures::setup_tempdir;
local $ENV{TZ} = 'UTC';

my %BASE = ( home => $tmp, config => {} );

{    # $self->now
    my $exp = DateTime->now( time_zone => 'local' );
    my $got = App::TimeTracker->now;
    is( $exp->ymd,               $got->ymd,               '$self->now: ymd' );
    is( $exp->strftime('%H:%M'), $got->strftime('%H:%M'), '$self->now: hh:mm' );
}

{    # beautify_seconds
    my @tests = (
        [ undef,                              '0' ],
        [ '0',                                '0' ],
        [ '59',                               '00:00:59' ],

t/TimeTracker/helpers.t  view on Meta::CPAN


{    # to / from
    my $class = Moose::Meta::Class->create_anon_class(
        superclasses => ['App::TimeTracker'],
        roles        => ['App::TimeTracker::Command::Core'],
    );
    my $class_name = $class->name;
    $class_name->_load_attribs_worked($class);

    no warnings 'redefine';
    local *DateTime::now =
        sub { return DateTime->new( year => 2011, month => 9, day => 7, hour => 12 ) };
    {
        my $t1 = $class_name->new( { %BASE, this => 'week', } );

        is( $t1->from->iso8601, '2011-09-05T00:00:00', 'From 1 ok' );
        is( $t1->to->iso8601,   '2011-09-11T23:59:59', 'To 1 ok' );
    }

    {
        my $t2 = $class_name->new( { %BASE, last => 'week', } );



( run in 0.382 second using v1.01-cache-2.11-cpan-05444aca049 )