App::TimeTracker - Track time spend on projects from the commandline


App-TimeTracker documentation Contained in the App-TimeTracker distribution.

Index


Code Index:

NAME

Top

App::TimeTracker - Track time spend on projects from the commandline

SYNOPSIS

Top

App::TimeTracker tracks time spend on various projects in a SQLite DB.

see perldoc tracker for a convenient frontend.

METHODS

Top

new

    my $tracker = App::TimeTracker->new;

Initiate a new tracker object.

Provided by Class::Accessor

Helper Methods

now

    my $now = $self->now;

Wrapper around DateTime->now that also sets the timezone to local

storage_location

    my $dir = $self->storage_location

Returns the path to the dir containing the stored tasks. Currently hardcoded to File::HomeDir plus .TimeTracker.

file

    my $path = $self->file( 'path/to/some/file' );
    my $path = $self->file( qw( path to some file) );

Prepends storage_location to the passed file path.

parse_datetime

    my $dt = $self->parse_datetime("1245");
    my $dt = $self->parse_datetime("0226-1245");

Convert a simple time / datetime into a DateTime object

Input can be a string containing Hour and Minute ("1245"), which will use todays date. Or a string containing Month Day followed by Hour & Minute (seperated by _ or -)

get_from_to

parse --from and --to, returns strings suitable for find_tasks

find_tasks

returns a list of filesnames (=tasks) that match the criteria specified on the commandline.

AUTHOR

Top

Thomas Klausner, <domm at cpan.org>

BUGS

Top

Please report any bugs or feature requests to bug-timetracker at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App::TimeTracker. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

Top

You can find documentation for this module with the perldoc command.

    perldoc App::TimeTracker

You can also look for information at:

* AnnoCPAN: Annotated CPAN documentation

http://annocpan.org/dist/App::TimeTracker

* CPAN Ratings

http://cpanratings.perl.org/d/App::TimeTracker

* RT: CPAN's request tracker

http://rt.cpan.org/NoAuth/Bugs.html?Dist=App::TimeTracker

* Search CPAN

http://search.cpan.org/dist/App::TimeTracker

ACKNOWLEDGEMENTS

Top

COPYRIGHT & LICENSE

Top


App-TimeTracker documentation Contained in the App-TimeTracker distribution.
package App::TimeTracker;

use 5.010;
use warnings;
use strict;
use version; our $VERSION = version->new('0.21');

use App::Cmd::Setup -app;
use base qw(Class::Accessor);
use App::TimeTracker::Task;
use App::TimeTracker::Projects;
use App::TimeTracker::Exceptions;
use DateTime;
use DateTime::Format::Strptime;
use File::Spec::Functions qw(splitpath catfile catdir);
use File::HomeDir;
use Getopt::Long;

__PACKAGE__->mk_accessors(qw(opts projects _old_data _schema));

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

sub storage_location {
    my $self = shift;

    if ( $INC{'Test/More.pm'} ) {
        return catdir('t/data');
    }
    else {
        return catdir( File::HomeDir->my_home, '.TimeTracker' );
    }
}

sub file {
    my $self = shift;
    return catfile( $self->storage_location, @_ );
}

sub parse_datetime {
    my ( $self, $datetime ) = @_;
    return $self->now unless $datetime;

    my $n = $self->now;

    my $date;
    eval {
        if ( $datetime =~ /^(?<hour>\d\d):?(?<minute>\d\d)$/ )
        {
            $date = DateTime->new(
                year      => $n->year,
                month     => $n->month,
                day       => $n->day,
                hour      => $+{hour},
                minute    => $+{minute},
                second    => 0,
                time_zone => 'local',
            );
        }
        elsif (
            $datetime =~ /
                        (?<month>\d\d)\.?(?<day>\d\d)
                        [-_]
                        (?<hour>\d\d):?(?<minute>\d\d)
                        /x
            )
        {
            $date = DateTime->new(
                year      => $n->year,
                month     => $+{month},
                day       => $+{day},
                hour      => $+{hour},
                minute    => $+{minute},
                second    => 0,
                time_zone => 'local',
            );
        }
    };
    if ($@) {
        X::BadDate->throw("Cannot parse $datetime into a date: $@");
    }
    return $date;
}

sub get_from_to {
    my ( $self, $opt ) = @_;

    my ( $from, $to );
    if ( my $this = $opt->{this} ) {
        $from = DateTime->now->truncate( to => $this );
        $to = $from->clone->add( $this . 's' => 1 );
    }
    elsif ( my $last = $opt->{last} ) {
        $from = DateTime->now->truncate( to => $last )
            ->subtract( $last . 's' => 1 );
        $to = $from->clone->add( $last . 's' => 1 );
    }
    elsif ( $opt->{from} && $opt->{to} ) {
        $from = DateTime::Format::ISO8601->parse_datetime( $opt->{from} );
        $to   = DateTime::Format::ISO8601->parse_datetime( $opt->{to} );
    }
    elsif ( $opt->{from} ) {
        $from = DateTime::Format::ISO8601->parse_datetime( $opt->{from} );
        $to   = $self->app->now;
    }
    elsif ( $opt->{to} ) {
        $from = $self->app->now->truncate( to => 'year' );
        $to = DateTime::Format::ISO8601->parse_datetime( $opt->{to} );
    }
    else {
        say "You need to specify some date limits!";
        exit;
    }
    return ( $from->ymd('') . $from->hms(''), $to->ymd('') . $to->hms('') );
}

sub find_tasks {
    my ( $self, $opt ) = @_;

    my $project = $opt->{project};
    our ( $from_cmp, $to_cmp ) = $self->get_from_to($opt);

    my @files = File::Find::Rule->file()->name(qr/\.(done|current)$/)->exec(
        sub {
            my ($file) = @_;
            $file =~ /(\d{8})-(\d{6})/;
            my $time = $1 . $2;
            return 1 if $time >= $from_cmp;
        }
        )->exec(
        sub {
            my ($file) = @_;
            $file =~ /(\d{8})-(\d{6})/;
            my $time = $1 . $2;
            return 1 if $time <= $to_cmp;
        }
        )->in( $self->app->storage_location . '/' );

    if ($project) {
        @files = grep {/$project/} @files;
    }

    return \@files;
}

# 1 is boring
q{ listeing to:
        Fat Freddys Drop: Based on a true story
};

__END__