Git Product home page Git Product logo

workpattern's Introduction

Workpattern Build Status

Calculates dates and durations whilst taking into account working and non-working times. It creates calendars similar to what you can find in project scheduling software like Microsoft project and Primavera P6.

Please use Github Issues to report bugs. If you have a question about the library, please use the workpattern tag on Stack Overflow. This tag is monitored by contributors.

Getting Started

Workpattern is a library with no monkey-patching and was tested using Travis against the following Ruby versions 1.9.3, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, ruby-head (3.1.0dev), jruby-19mode (9.2.9.0 (2.5.7) and jruby-head (9.3.0.0-SNAPSHOT (2.6.5).

You can install it using:

gem install workpattern

Or you can add it to your Gemfile with:

gem "workpattern"

Then run the bundle command to install it.

Use

Configure and Calculate

First create a Workpattern to hold all the working and resting times.

mywp=Workpattern.new 'My Workpattern',2011,10 

That line created a Workpattern called My Workpattern starting on 1-Jan-2011 and continuing for 10 years until 2020.

mywp is created with a 24 hour a day working time. Next step is to tell it to ignore weekends by making every Saturday and Sunday non-working.

mywp.resting :days => :weekend 

The Workpattern.clock method can be used to specify the non-working times for each weekday. Any class that responds to #hour and #min methods such as Time or DateTime can be used instead of Workpattern.clock.

mywp.resting :days =>:weekday, :from_time=>Workpattern.clock(0,0),:to_time=>Workpattern.clock(8,59) 
mywp.resting :days =>:weekday, :from_time=>Workpattern.clock(12,0),:to_time=>Workpattern.clock(12,59) 
mywp.resting :days =>:weekday, :from_time=>Workpattern.clock(18,0),:to_time=>Workpattern.clock(23,59) 

As well as :weekend and :weekday it is possible to use :mon, :tue, :wed, :thu, :fri, :sat, :sun or all.

With mywp setup, the #calc method is used to add 32 hours which must be supplied as the number of whole minutes (1920) to a date.

my_date=Time.gm 2011,9,1,9,0 
result_date = mywp.calc my_date,1920  # => 6/9/11@18:00

The result takes into account the non-working or resting times.

Subtracting a date is just as easy by using a negative number of minutes in #calc.

Finding the duration between two dates is also easy using the #diff method.

diff_result = mywp.diff my_date, result_date  # => 1920

Vacations can be added to the Workpattern using the #resting method:

mywp.resting :days => :all, :start => DateTime.civil(2011,5,1), :finish => DateTime.civil(2011,5,7)

Find out if a specific date and time is working or not.

mydate = DateTime.civil 2011,5,2,9,10
mywp.resting? mydate  # => true
mywp.working? mydate  # => false

Manage

# Fetch a specific Workpattern
Workpattern.get "My Workpattern"

# Delete a specific Workpattern
Workpattern.delete "My Workpattern"

# Delete all Workpatterns
Workpattern.clear

workpattern's People

Contributors

callenb avatar

Stargazers

Cristian Molina avatar Jason Weathered avatar Rey F. Diaz avatar Andre Vidic avatar  avatar sungjin.kang avatar 이원섭wonsup Lee/Alfonso avatar Andrew Vit avatar Araslanov Evgeny avatar Richard Biffin avatar  avatar

Watchers

Carl Leiby avatar  avatar Gábor Nagymajtényi avatar Richard Biffin avatar  avatar

Forkers

rkjbnz

workpattern's Issues

Improve performance

It isn't terribly slow, but I did notice places where it could be made faster. First thing to do is to look at benchmarking tests and then seeing what can be done to improve performance.

diff doesn't calculate properly from working to resting day

Big thanks to @mmartins888 for telling me about this one.

require 'workpattern'

mywp=Workpattern.new('My Workpattern',2013,3)
mywp.resting(:days => :weekend)
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(0,0),:to_time=>Workpattern.clock(8,59))
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(12,0),:to_time=>Workpattern.clock(12,59))
mywp.resting(:days =>:weekday, :from_time=>Workpattern.clock(18,0),:to_time=>Workpattern.clock(23,59))

mydate1=DateTime.civil(2013,9,27,0,0,0)
mydate2=DateTime.civil(2013,9,27,23,59,59)

mywp.resting(:start=>mydate1,:finish=>mydate2, :days =>:all, :from_time=>Workpattern.clock(0,0), :to_time=>Workpattern.clock(23,59))

diff recognizes 27/sep as holiday if i start with a resting day with a finish resting day.

mywp.diff(DateTime.civil(2013,9,27,5,0),DateTime.civil(2013,9,27,10,0))
=> 0

The problem is that diff gives the wrong answer when starting from a working day and time (26-Sep@17:00) and ending in a resting day (27-Sep@10:00).

mywp.diff(DateTime.civil(2013,9,26,17,0),DateTime.civil(2013,9,27,10,0))
=> 120

This should be 60

Is the Wiki necessary or should it be on a web site?

I had forgotten I had done anything on the wiki and I don't know if it is even correct.

It should be validated that it is correct for the latest version and updated where necessary as a first step.

I then need to decide where that documentation should go - should a README do for it and then add extra through a web site blog?

Conflict with rails

Hello,

Thanks for this great gem.

To make it better you have to change some of the naming of methods to remove the conflict between the classes.

In your gem you are adding additional methods to the Integer class which will conflict with the rails such as minutes witch will accepts two arguments but in rails no arguments. Rails uses this method to calculate the number of seconds. so my suggestion is to change the name of the methods to gust add prefix to the method for example "wp_".

thanks again

Specify Ruby version on Rubygems.org

The Workpattern listing on Rubygems.org specifies the Ruby version as being >=0 and although I don't know the first version it will work with, this should be set to the earliest used to test

2 tests fail with Ruby 2.0

When running tests under Ruby 2.0, I get two errors. Since I'm off on holiday for a couple of weeks I won't be addressing these just yet.

[13/64] TestDay#test_subtract_minutes_in_a_patterned_day = 0.01 s

  1. Error:
    test_subtract_minutes_in_a_patterned_day(TestDay):
    TypeError: Rational can't be coerced into Rational for bitwise arithmetic
    /home/barrie/dev/wp/lib/workpattern/hour.rb:64:in `&'

AND

[45/64] TestWorkpattern#test_calculate_across_week_patterns = 0.04 s
2) Error:
test_calculate_across_week_patterns(TestWorkpattern):
TypeError: Rational can't be coerced into Rational for bitwise arithmetic
/home/barrie/dev/wp/lib/workpattern/hour.rb:64:in `&'

Incomplete tests for Week

Empty tests for:

  • add minutes in a resting week
  • add minutes in a patterned week
  • subtract minutes in a resting week
  • subtract minutes in a patterned week
  • create complex patterns

Add a way to persist the workpatterns and definitions

At the moment the user has to work out their own way of storing information to re-create a Workpattern later on. It would be very useful to have a configurable way of doing this, particularly if it was capable of making use of different storage such as a database or file formats.

travis.ci build 9 failed

#7 midnight flag should override hour and minutes

The JRuby ci failed with:

$ bundle exec rake

22/home/vagrant/.rvm/rubies/jruby-1.6.7.2-d19/bin/jruby -I"lib:test" -I"/home/vagrant/.rvm/gems/jruby-1.6.7.2-d19/gems/rake-0.9.2.2/lib" "/home/vagrant/.rvm/gems/jruby-1.6.7.2-d19/gems/rake-0.9.2.2/lib/rake/rake_test_loader.rb" "test/test_clock.rb" "test/test_day.rb" "test/test_workpattern.rb" "test/test_hour.rb" "test/test_week.rb" "test/test_workpattern_module.rb" "test/test_helper.rb"

23Loaded suite /home/vagrant/.rvm/gems/jruby-1.6.7.2-d19/gems/rake-0.9.2.2/lib/rake/rake_test_loader

24Started

25........................................E...................org.jruby.exceptions.RaiseException: (SystemExit) exit

26.....

27Finished in 6.294000 seconds.

28

29 1) Error:

30test_subtract_minutes_in_a_resting_week(TestWeek):

31SystemStackError: stack level too deep

32 org/jruby/RubyArray.java:1615:in `each'

33 /home/vagrant/builds/callenb/workpattern/test/test_week.rb:141:in `test_subtract_minutes_in_a_resting_week'

34 org/jruby/RubyBasicObject.java:1698:in `send'

35

3665 tests, 1410 assertions, 0 failures, 1 errors, 0 skips

37

38Test run options: --seed 47237

39rake aborted!

40Command failed with status (-1): [/home/vagrant/.rvm/rubies/jruby-1.6.7.2-d1...]

41

42Tasks: TOP => default => test

43(See full trace by running task with --trace)

44

45Done. Build script exited with: 1

Turns out I was repeatedly calling subtract on a Week workpattern per day over a number of years when there wasn't any minutes in the week. I changed the code so it jumped to the first date in the week when dealing with subtraction in a week with 0 working minutes. Tests were faster too!!!.

RDoc documentation could be more helpful

The RDoc documentation contains a lot of noise and most likely puts off potential users of the gem.

The documentation produced should be reviewed and updated ware necessary to clearly show the public api and how it can be used.

Incomplete tests for Workpattern

The following tests are not completed

  • add minutes in a patterned workpattern
  • subtract minutes in a patterned workpattern
  • calculate difference between minutes in resting workpattern
  • calculate difference between minutes in pattern workpattern

Adding minutes starting from a resting period in a patterned hour failed

I have been rewriting the tests inspired by the Ruby Rogues podcasts I am listening to. In doing so I have found bugs,

In this one I have an hour that has some resting minutes and I start from one of them and try to add the exact minutes to the end of the hour. It gives the wrong result.

midnight flag should override hour and minutes

Find whilst completing tests for Class Week.
The midnight flag should override hour and minutes but it doesn't and instead of calculating from midnight it calculates from the set time in the following day.

The Workpattern gem should never create this situation for itself, but if it did then it wouldn't work

available minutes not calculating correctly for a time of 00:01

Find whilst completing tests for Class Week

start=DateTime.new(2000,1,1,0,0)
finish=DateTime.new(2005,12,31,8,59)
working_week=Workpattern::Week.new(start,finish,1)
result_date, result_duration= working_week.calc(DateTime.new(2005,12,31,0,1),-2) #-> result_date is 2005-12-30T23:58 but should be 2005-12-30T23:58
result_date, result_duration= working_week.calc(DateTime.new(2000, 1,1,0,1),-2) #-> result_duration is -2 but should be -1

Calculations are always in utc and so do not take into account timezones

It has always been my intention to calculate using the timezone however it is made available.

To be quite open about this, I have coded and tested this with existing tests (see the use-utc branch). Only one test failed and that was when the calculation went over the Autumn time change (this was London timezone). Calculating by hand, I confirmed the new result was in fact right for the calculation.

I need more tests to be confident as there are a lot of timezones. If we fast forward to the day there are enough tests to be confident it can handle different timezones then releasing it will be a breaking change, though arguably fixing a bug. Navigating that change is my big challenge. Any advice is very much appreciated. The current version has been downloaded over 1000 times and I don't know how many actually use it so the impact of my breaking change is unknown.

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.