• Stars
    star
    415
  • Rank 104,301 (Top 3 %)
  • Language
    Ruby
  • License
    MIT License
  • Created almost 14 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Time of day and shift types for Ruby

Tod

Supplies TimeOfDay class that includes parsing, strftime, comparison, and arithmetic.

Supplies Shift to represent a period of time, using a beginning and ending TimeOfDay. Allows to calculate its duration and to determine if a TimeOfDay is included inside the shift. For nightly shifts (when beginning time is greater than ending time), it supposes the shift ends the following day.

Installation

gem install tod

Examples

Loading Tod

require 'tod'

Creating from hour, minute, and second

Tod::TimeOfDay.new 8                                # => 08:00:00
Tod::TimeOfDay.new 8, 15, 30                        # => 08:15:30

Parsing text

Strings only need to contain an hour. Minutes, seconds, AM or PM, and colons are all optional.

Tod::TimeOfDay.parse "8"                            # => 08:00:00
Tod::TimeOfDay.parse "8am"                          # => 08:00:00
Tod::TimeOfDay.parse "8pm"                          # => 20:00:00
Tod::TimeOfDay.parse "8p"                           # => 20:00:00
Tod::TimeOfDay.parse "9:30"                         # => 09:30:00
Tod::TimeOfDay.parse "15:30"                        # => 15:30:00
Tod::TimeOfDay.parse "3:30pm"                       # => 15:30:00
Tod::TimeOfDay.parse "1230"                         # => 12:30:00
Tod::TimeOfDay.parse "3:25:58"                      # => 03:25:58
Tod::TimeOfDay.parse "515p"                         # => 17:15:00
Tod::TimeOfDay.parse "151253"                       # => 15:12:53
Tod::TimeOfDay.parse "noon"                         # => 12:00:00
Tod::TimeOfDay.parse "midnight"                     # => 00:00:00

Tod::TimeOfDay.parse raises an ArgumentError if the argument to parse is not parsable. Tod::TimeOfDay.try_parse will instead return nil if the argument is not parsable.

Tod::TimeOfDay.try_parse "3:30pm"                   # => 15:30:00
Tod::TimeOfDay.try_parse "foo"                      # => nil

You can also give a block to parse to handle special input with your own logic.

Tod::TimeOfDay.parse "25" do |time_string|
  Tod::TimeOfDay.new(time_string.to_i % 24)
end                                                 # => 01:00:00

Values can be tested with Tod::TimeOfDay.parsable? to see if they can be parsed.

Tod::TimeOfDay.parsable? "3:30pm"                   # => true
Tod::TimeOfDay.parsable? "foo"                      # => false

Adding or subtracting time

Seconds can be added to or subtracted from Tod::TimeOfDay objects. Time correctly wraps around midnight.

Tod::TimeOfDay.new(8) + 3600                        # => 09:00:00
Tod::TimeOfDay.new(8) - 3600                        # => 07:00:00
Tod::TimeOfDay.new(0) - 30                          # => 23:59:30
Tod::TimeOfDay.new(23,59,45) + 30                   # => 00:00:15

Comparing

Tod::TimeOfDay includes Comparable.

Tod::TimeOfDay.new(8) < Tod::TimeOfDay.new(9)            # => true
Tod::TimeOfDay.new(8) == Tod::TimeOfDay.new(9)           # => false
Tod::TimeOfDay.new(9) == Tod::TimeOfDay.new(9)           # => true
Tod::TimeOfDay.new(10) > Tod::TimeOfDay.new(9)           # => true

Formatting

Format strings are passed to Time#strftime.

Tod::TimeOfDay.new(8,30).strftime("%H:%M")          # => "08:30"
Tod::TimeOfDay.new(17,15).strftime("%I:%M %p")      # => "05:15 PM"
Tod::TimeOfDay.new(22,5,15).strftime("%I:%M:%S %p") # => "10:05:15 PM"

Or a Rails style to_formatted_s is aliased to to_s.

Tod::TimeOfDay.new(8,30).to_s(:short)    # => "8:30 am"

Or i18n in a Rails ERB view.

<%= l Tod::TimeOfDay.new(8, 30), format: :short %>

Add new formatters to Tod::TimeOfDay::FORMATS.

Tod::TimeOfDay::FORMATS[:seconds_only] = "%S"
Tod::TimeOfDay.new(8,30,57).to_s(:seconds_only)  # => "57"

Rounding

Round to the given nearest number of seconds.

Tod::TimeOfDay.new(8,15,31).round(5)     # => "08:15:30"
Tod::TimeOfDay.new(8,15,34).round(60)    # => "08:16:00"
Tod::TimeOfDay.new(8,02,29).round(300)   # => "08:00:00"

Convenience methods for dates and times

Pass a date to Tod::TimeOfDay#on and it will return a time with that date and time, in the time zone of the ruby runtime (Time.now.zone).

tod = Tod::TimeOfDay.new 8, 30                  # => 08:30:00
tod.on Date.today                               # => 2010-12-29 08:30:00 -0600

Tod offers Date#at and Time#to_time_of_day. Require 'tod/core_extensions' to enable.

require 'tod/core_extensions'
tod = Tod::TimeOfDay.new 8, 30                  # => 08:30:00
Date.today.at tod                               # => 2010-12-29 08:30:00 -0600
Time.now.to_time_of_day                         # => 16:30:43
DateTime.now.to_time_of_day                     # => 16:30:43

Conversion method

Tod provides a conversion method which will handle a variety of input types:

Tod::TimeOfDay(Tod::TimeOfDay.new(8, 30))           # => 08:30:00
Tod::TimeOfDay("09:45")                        # => 09:45:00
Tod::TimeOfDay(Time.new(2014, 1, 1, 12, 30))   # => 12:30:00
Tod::TimeOfDay(Date.new(2014, 1, 1))           # => 00:00:00

Shifts

Tod::Shift is a range-like object that represents a period of time, using a beginning and ending Tod::TimeOfDay. Allows to calculate its duration and to determine if a Tod::TimeOfDay is included inside the shift. For nightly shifts (when beginning time is greater than ending time), it supposes the shift ends the following day. Tod::Shift behaves like a Ruby range in that it defaults to inclusive endings. For exclusive endings, pass true as the third argument (like a Ruby range).

Creating from Tod::TimeOfDay

Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17))
Tod::Shift.new(Tod::TimeOfDay.new(22), Tod::TimeOfDay.new(4))

Duration

Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17)).duration # => 28800
Tod::Shift.new(Tod::TimeOfDay.new(20), Tod::TimeOfDay.new(2)).duration # => 21600

Include?

Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17)).include?(Tod::TimeOfDay.new(12)) # => true
Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17)).include?(Tod::TimeOfDay.new(7))  # => false
Tod::Shift.new(Tod::TimeOfDay.new(20), Tod::TimeOfDay.new(4)).include?(Tod::TimeOfDay.new(2))  # => true
Tod::Shift.new(Tod::TimeOfDay.new(20), Tod::TimeOfDay.new(4)).include?(Tod::TimeOfDay.new(18)) # => false

#include? respects exclusive endings.

Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(9)).include?(Tod::TimeOfDay.new(9)) # => true
Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(9), true).include?(Tod::TimeOfDay.new(9)) # => false

Overlaps?

breakfast = Tod::Shift.new(Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(11))
lunch = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(14))
breakfast.overlaps?(lunch) # => true
lunch.overlaps?(breakfast) # => true

dinner = Tod::Shift.new(Tod::TimeOfDay.new(18), Tod::TimeOfDay.new(20))
dinner.overlaps?(lunch) # => false

# Exclude ending
morning_shift = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17), true)
evening_shift = Tod::Shift.new(Tod::TimeOfDay.new(17), Tod::TimeOfDay.new(1), true)
morning_shift.overlaps?(evening_shift) # => false

Contains?

workday = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17))
lunch = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(14))
workday.contains?(lunch) # => true
lunch.contains?(workday) # => false

dinner = Shift.new(TimeOfDay.new(18), TimeOfDay.new(20))
dinner.overlaps?(lunch) # => false

Rails Time Zone Support

If Rails time zone support is loaded, Date#on and Tod::TimeOfDay#at (when given a Date) will automatically use Time.zone.

When Tod::TimeOfDay#on is given a Time or Time-like object like ActiveSupport::TimeWithZone, Tod will ignore the specified timezone and return the time on that date in UTC. In order to produce an object with the correct time and time zone, pass in an ActiveSupport::TimeZone object. Date#at has analogous behavior.

time = Time.now.in_time_zone("US/Eastern")           # => Mon, 24 Sep 2018 05:07:23 EDT -04:00
tod.on time                                          # => Mon, 24 Sep 2018 08:30:00 UTC +00:00
tod.on time, time.time_zone                          # => Mon, 24 Sep 2018 08:30:00 EDT -04:00
tod.on time, Time.find_zone!("US/Mountain")          # => Mon, 24 Sep 2018 08:30:00 MDT -06:00
Date.tomorrow.at tod, Time.find_zone!("US/Mountain") # => Tue, 25 Sep 2018 08:30:00 MDT -06:00

ActiveRecord Attribute Support

Tod::TimeOfDay can be used as an ActiveRecord attribute to store Tod::TimeOfDay directly in a column of the time type.

Example:

ActiveModel::Type.register(:time_only, Tod::TimeOfDayType)
ActiveRecord::Type.register(:time_only, Tod::TimeOfDayType)

class Order < ActiveRecord::Base
  attribute :time, :time_only
end
order = Order.create(time: Tod::TimeOfDay.new(9,30))
order.time                                      # => 09:30:00

In Rails, this can be used with time_select in forms like so:

f.time_select :time, ignore_date: true

Or with simple_form:

f.input :time, as: :time, ignore_date: true

MongoDB Support

Tod includes optional serialization support for Tod::TimeOfDay to be serialized to MongoDB.

require 'tod/mongoization'

Upgrading from Versions Prior to 2.0.0

Tod has a new focus on not polluting the global namespace.

Tod no longer puts Tod::TimeOfDay and Tod::Shift in the global namespace by default. You can either fully qualify access to these classes or include Tod in the global namespace.

require 'tod'
include Tod # TimeOfDay and Shift are now in the global namespace like in versions prior to 2.0.0

Tod no longer automatically extends the Time and Date classes. Require them explicitly.

require 'tod/core_extensions'
tod = Tod::TimeOfDay.new 8, 30                  # => 08:30:00
Date.today.at tod                               # => 2010-12-29 08:30:00 -0600
Time.now.to_time_of_day                         # => 16:30:43
DateTime.now.to_time_of_day                     # => 16:30:43

Tod no longer automatically includes MongoDB serialization methods in Tod::TimeOfDay. Require them explicitly.

require 'tod/mongoization'

Compatibility

Build Status

Tod is tested against Ruby 2.6.x and Rails 6.x.

License

Copyright (c) 2010-2021 Jack Christensen, released under the MIT license

More Repositories

1

pgx

PostgreSQL driver and toolkit for Go
Go
8,422
star
2

tern

The SQL Fan's Migrator
Go
656
star
3

surus

PostgreSQL extensions for ActiveRecord
Ruby
395
star
4

sqlfmt

SQL Formatter
Yacc
337
star
5

pglogrepl

PostgreSQL logical replication library for Go.
Go
325
star
6

pgtype

Go
308
star
7

puddle

Generic resource pool for Go
Go
294
star
8

pgconn

Go
180
star
9

pgproto3

Go
160
star
10

pgerrcode

Package pgerrcode contains constants for PostgreSQL error codes.
Go
148
star
11

pgmock

Go
119
star
12

edge

Edge provides graph functionality to ActiveRecord.
Ruby
89
star
13

mat-view-strat-pg

Materialized View Strategies Using PostgreSQL
PLpgSQL
61
star
14

go_db_bench

Benchmarks for database/drivers from Go
Go
52
star
15

json_api_bench

Benchmark of Rails and PostgreSQL JSON generation techniques
Ruby
32
star
16

pgxlisten

pgxlisten provides higher level PostgreSQL LISTEN / NOTIFY tooling built on pgx.
Go
29
star
17

tpr

The Pithy Reader - a fast, simple, and lightweight feed aggregator and reader
Go
22
star
18

pgxutil

Go
20
star
19

pgx-top-to-bottom

HTML
18
star
20

pgxjob

pgxjob provides a job queue implementation using PostgreSQL.
Go
16
star
21

pg-custom-aggregate-grt

PostgreSQL custom aggregate greatest running total implemented in PL/pgSQL and C
PLpgSQL
16
star
22

react2fs

Run command in reaction to file system events
Go
15
star
23

chunkreader

Go
14
star
24

overload

HTTP load tester
Go
14
star
25

pgxrecord

pgxrecord is a tiny framework for CRUD operations and data mapping.
Go
14
star
26

pgx-zerolog

Go
13
star
27

pgio

Package pgio is a low-level toolkit building messages in the PostgreSQL wire protocol.
Go
12
star
28

command_model

CommandModel - when update_attributes isn't enough.
Ruby
12
star
29

booklog

Go
10
star
30

pgtocsv

pgtocsv executes a query on a PostgreSQL database and outputs the results in CSV.
Go
10
star
31

pgx-shopspring-decimal

Go
9
star
32

writable-cte-examples

Examples of Writable Common Table Expressions in PostgreSQL
Ruby
9
star
33

pgxdata

Go
9
star
34

pgx-zap

Go
9
star
35

numfmt

Number formatting in Go
Go
9
star
36

pgservicefile

pgservicefile is a parser PostgreSQL for service files (e.g. .pg_service.conf)
Go
8
star
37

pgsql

Go
8
star
38

pgx-gofrs-uuid

Go
8
star
39

go_map_vs_switch

Benchmark for Go map of functions vs. switch
Go
7
star
40

pg-extid

Go
7
star
41

go-extid

Go
7
star
42

pgundolog

pgundolog is a system for rolling back changes to a PostgreSQL database without using transactions.
PLpgSQL
7
star
43

hannibal

Experimental PostgreSQL web application server
Go
5
star
44

cavein

TCP tunnel that designed for testing applications with random connection losses
Go
5
star
45

pgxrepl

Replication client library for PostgreSQL in Go using the pgx driver
Go
5
star
46

quo_vadis

Really simple and fast HTTP Router
Go
5
star
47

text_tunnel

Use your local text editor to edit files on remote servers.
Ruby
5
star
48

pgpassfile

Go
4
star
49

csvtopg

csvtopg copies a CSV to a PostgreSQL database.
Go
4
star
50

chicagolang-feb-2015

Slides for Building Command Line Applications in Go
Go
4
star
51

go_router_tutorial

Tutorial to build a simple HTTP router in Go
Go
4
star
52

doublecheck

Doublecheck your database before it is too late
Go
4
star
53

why-pgx

Slides for lightning talk on pgx
4
star
54

gel

Go Compiled Templates
Go
3
star
55

ego

Experimental shorthand for Go error handling.
Go
3
star
56

pgx_notify_lost_connection

Test for PGX WaitForNotification when connection is lost
Go
3
star
57

pigeon-exp-xmlpp

Experimenting with pigeon PEG generator for Go
Go
3
star
58

doublecheck_view

Ruby gem for integrating doublecheck view pattern with database integration tests
Ruby
3
star
59

envconf

Envconf is a simple, zero dependency library for managing configuration from the environment.
Go
3
star
60

cachet

The cache for all your Ts
Go
2
star
61

go-hello

Go program to practice packaging
Go
2
star
62

pgxsql

Go
2
star
63

flex

Go
2
star
64

cgol-rust

Quick, experimental port of Go cgol to Rust
Rust
2
star
65

assert_db_rejects

Test database level constraints with ActiveRecord
Ruby
2
star
66

dailyprogrammer

Go
2
star
67

imperator

Imperator is an imperative normalization and validation library for Go.
Go
2
star
68

pg95-whats-new

What's new in PostgreSQL 9.5
PLpgSQL
2
star
69

go-intro

Quick introduction to Go -- sample project and speaker notes
Go
2
star
70

pgxbench

PLSQL
2
star
71

react2fs-deb

react2fs Debian package
Go
2
star
72

sadpath

sadpath provides a simple way to centralize error handling and reduce boilerplate.
Go
2
star
73

ppg

ppg runs a SQL file multiple times in parallel
Go
2
star
74

box

Go
2
star
75

tern-deb

Build scripts for debian package for tern
Go
2
star
76

sqlfmt-deb

sqlfmt Debian package
Go
2
star
77

ctxio

Go
2
star
78

jchat

Go
2
star
79

exp-go-repl

Experimenting with yacc
Go
2
star
80

webby-template-minimal-website

Minimal possible website template for Webby
2
star
81

go-server-closed-tcp-conn-os-inconsistencies

Example of differing server closed TCP connections on Linux and Windows
2
star
82

form

HTTP forms for Go
Go
2
star
83

tpr-deb

The Pithy Reader Debian Package
Go
2
star
84

mp

mp (map parser) provides a parser that parses maps into types defined at runtime.
Go
2
star
85

pgx_issues

Test and example cases for pgx issues
Go
1
star
86

context-rows-cancel

Test of Go database/sql context cancelation
Go
1
star
87

pgx845

This is a test application for https://github.com/jackc/pgx/issues/845.
Go
1
star
88

markovbot

Go
1
star
89

reggie

Regular expression builder and tester for Ruby
Ruby
1
star
90

snake_case

Go
1
star
91

cbc-sinatra-crash

Test app demonstrating a crash
Ruby
1
star
92

hackers-delight

Hacker's Delight Exercises and Experiments
Go
1
star
93

pg_pl_bench

Go
1
star
94

booklogh

Experimental port of Booklog to Hannibal
PLpgSQL
1
star
95

alt_record

An alternative implementation of the active record pattern for Ruby
Ruby
1
star
96

structify

Go
1
star
97

testdb

Test database manager
Go
1
star
98

form_model

Ruby
1
star
99

homebrew-formulas

Jack Christensen's Formulas
Ruby
1
star
100

go_database_sql_retry_bug

Test application to determine if database/sql auto-retry logic is safe
Go
1
star