App-Jiffy

 view release on metacpan or  search on metacpan

META.json  view on Meta::CPAN

      },
      "develop" : {
         "requires" : {
            "Dist::Milla" : "v1.0.15",
            "Test::Pod" : "1.41"
         }
      },
      "runtime" : {
         "requires" : {
            "Dancer" : "0",
            "DateTime" : "0",
            "DateTime::Format::Strptime" : "0",
            "JSON::MaybeXS" : "0",
            "MongoDB" : "v1.0.0",
            "Moo" : "0",
            "YAML::Any" : "0",
            "perl" : "5.008005"
         }
      },
      "test" : {
         "requires" : {
            "Capture::Tiny" : "0",

META.yml  view on Meta::CPAN

no_index:
  directory:
    - t
    - xt
    - inc
    - share
    - eg
    - examples
requires:
  Dancer: '0'
  DateTime: '0'
  DateTime::Format::Strptime: '0'
  JSON::MaybeXS: '0'
  MongoDB: v1.0.0
  Moo: '0'
  YAML::Any: '0'
  perl: '5.008005'
resources:
  bugtracker: https://github.com/lejeunerenard/jiffy/issues
  homepage: https://github.com/lejeunerenard/jiffy
  repository: https://github.com/lejeunerenard/jiffy.git
version: '0.09'

cpanfile  view on Meta::CPAN

requires 'perl', '5.008005';

requires 'MongoDB', '>= 1.0.0';
requires 'Moo';
requires 'DateTime';
requires 'DateTime::Format::Strptime';
requires 'YAML::Any';
requires 'Dancer';
requires 'JSON::MaybeXS';

on test => sub {
  requires 'Test::More', '0.88';
  requires 'Capture::Tiny';
};

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

  my $title;
  if ( ref $options ne 'HASH' ) {
    $title = $options;
    undef $options;
  } else {
    $title = shift;
  }

  my $start_time;

  my $LocalTZ = DateTime::TimeZone->new( name => 'local' );    # For caching
  my $now = DateTime->now( time_zone => $LocalTZ );

  if ( $options->{time} ) {
    require DateTime::Format::Strptime;

    # @TODO Figure out something more flexible and powerful to get time

    # First try H:M:S
    my $strp = DateTime::Format::Strptime->new(
      pattern   => '%T',
      time_zone => $LocalTZ,
    );
    $start_time = $strp->parse_datetime( $options->{time} );

    # If no time found try just H:M
    if ( not $start_time ) {
      my $strp = DateTime::Format::Strptime->new(
        pattern   => '%R',
        time_zone => $LocalTZ,
      );
      $start_time = $strp->parse_datetime( $options->{time} );
    }

    # Make sure the date part of the datetime is not set to the
    # beginning of time.
    if ( $start_time and $start_time->year < $now->year ) {
      $start_time->set(

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

  my $self    = shift;
  my $options = shift;
  my $from;
  if ( ref $options ne 'HASH' ) {
    $from = $options;
    undef $options;
  } else {
    $from = shift;
  }

  my $from_date = DateTime->today( time_zone => 'local' );

  if ( defined $from ) {
    $from_date->subtract( days => $from );
  }

  my @entries = App::Jiffy::TimeEntry::search(
    $self->cfg,
    query => {
      start_time => { '$gt' => $from_date, },
      $self->remove_terminators,

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

  my $query_text = shift;
  my $options    = shift;
  my $days;
  if ( ref $options ne 'HASH' ) {
    $days = $options;
    undef $options;
  } else {
    $days = shift;
  }

  my $from_date = DateTime->today( time_zone => 'local' );

  if ( defined $days ) {
    $from_date->subtract( days => $days );
  }

  my @entries = App::Jiffy::TimeEntry::search(
    $self->cfg,
    query => {
      start_time => { '$gt' => $from_date, },
      $self->remove_terminators,

lib/App/Jiffy/TimeEntry.pm  view on Meta::CPAN

  is  => 'rw',
  isa => sub {
    die 'id must be a MongoDB::OID'
      unless blessed $_[0] and $_[0]->isa('MongoDB::OID');
  },
);

has start_time => (
  is  => 'rw',
  isa => sub {
    die 'start_time is not a DateTime object'
      unless blessed $_[0] and $_[0]->isa('DateTime');
  },
  default => sub {
    DateTime->now();
  },
);

has title => (
  is       => 'rw',
  required => 1,
);

has _duration => ( is => 'rw', );

lib/App/Jiffy/TimeEntry.pm  view on Meta::CPAN

    },
    sort => {
      start_time => 1,
    },
    limit => 1,
  );

  if (@entry_after) {
    return $entry_after[0]->start_time->subtract_datetime( $self->start_time );
  } else {
    return DateTime->now->subtract_datetime( $self->start_time );
  }
}

=head2 find

C<find> will return a single document. The query will use the provided C<_id>.

=cut

sub find {

lib/App/Jiffy/TimeEntry.pm  view on Meta::CPAN

    $entries = $entries->sort($sort);
  }

  if ($limit) {
    $entries = $entries->limit($limit);
  }

  # Return undef if nothing was found
  return unless $entries;

  my $LocalTZ = DateTime::TimeZone->new( name => 'local' );    # For caching

# @TODO create a subclass of the MongoDB cursor that allows chaining of results like MongoDB
  map {
    $_->{start_time}->set_time_zone($LocalTZ);    # Convert to local tz
    App::Jiffy::TimeEntry->new(
      id         => $_->{_id},
      title      => $_->{title},
      start_time => $_->{start_time},
      cfg        => $cfg,
      )

lib/App/Jiffy/View/Timesheet.pm  view on Meta::CPAN

package App::Jiffy::View::Timesheet;

use strict;
use warnings;

use App::Jiffy::TimeEntry;
use App::Jiffy::Util::Duration qw/round/;
use DateTime;

sub render {
  my $entries = shift;
  my $options = shift;
  my $from    = $options->{from};

  # Header
  if ($from) {
    print "The past " . $from . " days' timesheet:\n\n";
  } else {

lib/App/Jiffy/View/Timesheet.pm  view on Meta::CPAN

  my $current_day = $entries->[0]->start_time->clone->truncate( to => 'day' );
  if ($from) {
    print "Date: " . $current_day->mdy('/') . "\n";
  }

  foreach my $entry (@$entries) {

    my $start_time = $entry->start_time->clone;

    if (
      DateTime->compare( $current_day, $start_time->truncate( to => 'day' ) )
      == -1 )
    {
      $current_day = $start_time->truncate( to => 'day' );
      print "\nDate: " . $current_day->mdy('/') . "\n";
    }

    # Get the deltas
    my $duration = $entry->duration;
    my %deltas   = $duration->deltas;

t/01-time-entry.t  view on Meta::CPAN

  };
};
subtest 'Class methods' => sub {
  subtest 'last_entry' => sub {
    my $time_entry = App::Jiffy::TimeEntry->new(
      title => 'Latest thing',
      cfg   => $cfg,

      # Add a day to ensure it comes up last. If you don't the previously
      # created item can come up as last
      start_time => DateTime->now->add( days => 1 ),
    );
    ok $time_entry->save, 'create entry';

    my $last_entry = App::Jiffy::TimeEntry::last_entry($cfg);
    is $last_entry->id, $time_entry->id, 'received latest entry';
  };
};

done_testing;

t/02-jiffy-app.t  view on Meta::CPAN

subtest 'STDOUT' => sub {
  my @layers = PerlIO::get_layers(STDOUT);

  ok grep( /utf8/, @layers ), 'set to utf8';
};

subtest 'add_entry' => sub {
  subtest 'works on UTC edge cases' => sub {
    {
      no warnings 'redefine';
      local *DateTime::now = sub {
        DateTime->new(
          day       => 10,
          hour      => 20,
          minute    => 0,
          year      => 2016,
          month     => 2,
          time_zone => 'local',
        );
      };
      $ENV{TZ} = 'America/Chicago';

t/02-jiffy-app.t  view on Meta::CPAN

      } );
    };

    like $stdout, qr/\d{1,2}:\d{2}/, 'found times';
  };

  subtest 'can be rounded' => sub {
    ok $db->drop, 'cleared db';

    # Seed db
    my $now = DateTime->now->subtract( hours => 1 );
    generate(
      $cfg,
      [ {
          start_time => sub {
            return $now->clone()->set_minute(0);
          },
        },
        {
          start_time => sub {
            return $now->clone()->set_minute(23);

t/lib/CreateTimeEntries.pm  view on Meta::CPAN

use App::Jiffy::TimeEntry;

use parent qw( Exporter );

our @EXPORT = qw/generate/;

sub generate {
  my $cfg     = shift;
  my $entries = shift;

  my $now = DateTime->now( time_zone => 'local' );

  for my $i ( 0 .. $#$entries ) {
    my $entry = $entries->[$i];
    my $start_time;

    if ( ref $entry->{start_time} eq 'CODE' ) {
      $start_time = $entry->{start_time}->();
    } elsif ( ref $entry->{start_time} eq 'HASH' ) {
      $start_time = $now->clone->subtract( %{ $entry->{start_time} } );
    }



( run in 0.346 second using v1.01-cache-2.11-cpan-2b0bae70ee8 )