datetimepicker 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/app/assets/javascripts/datetimepicker.js.coffee +12 -0
- data/app/assets/javascripts/datetimepicker/bootstrap_datepicker.js +401 -0
- data/app/assets/javascripts/datetimepicker/bootstrap_timepicker.js +800 -0
- data/app/assets/stylesheets/_datetimepicker.css.scss +2 -0
- data/app/assets/stylesheets/datetimepicker/bootstrap_datepicker.css +156 -0
- data/app/assets/stylesheets/datetimepicker/bootstrap_timepicker.css +81 -0
- data/datetimepicker.gemspec +17 -0
- data/lib/datetimepicker.rb +14 -0
- data/lib/datetimepicker/activerecord.rb +122 -0
- data/lib/datetimepicker/date_and_time_manipulator.rb +84 -0
- data/lib/datetimepicker/date_formats.rb +2 -0
- data/lib/datetimepicker/engine.rb +5 -0
- data/lib/datetimepicker/simple_form/inputs/datetimepicker_input.rb +29 -0
- data/lib/datetimepicker/version.rb +3 -0
- metadata +65 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
/*!
|
2
|
+
* Datepicker for Bootstrap
|
3
|
+
*
|
4
|
+
* Copyright 2012 Stefan Petre
|
5
|
+
* Licensed under the Apache License v2.0
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
.datepicker {
|
10
|
+
top: 0;
|
11
|
+
left: 0;
|
12
|
+
padding: 4px;
|
13
|
+
margin-top: 1px;
|
14
|
+
-webkit-border-radius: 4px;
|
15
|
+
-moz-border-radius: 4px;
|
16
|
+
border-radius: 4px;
|
17
|
+
/*.dow {
|
18
|
+
border-top: 1px solid #ddd !important;
|
19
|
+
}*/
|
20
|
+
}
|
21
|
+
.datepicker:before {
|
22
|
+
content: '';
|
23
|
+
display: inline-block;
|
24
|
+
border-left: 7px solid transparent;
|
25
|
+
border-right: 7px solid transparent;
|
26
|
+
border-bottom: 7px solid #ccc;
|
27
|
+
border-bottom-color: rgba(0, 0, 0, 0.2);
|
28
|
+
position: absolute;
|
29
|
+
top: -7px;
|
30
|
+
left: 6px;
|
31
|
+
}
|
32
|
+
.datepicker:after {
|
33
|
+
content: '';
|
34
|
+
display: inline-block;
|
35
|
+
border-left: 6px solid transparent;
|
36
|
+
border-right: 6px solid transparent;
|
37
|
+
border-bottom: 6px solid #ffffff;
|
38
|
+
position: absolute;
|
39
|
+
top: -6px;
|
40
|
+
left: 7px;
|
41
|
+
}
|
42
|
+
.datepicker > div {
|
43
|
+
display: none;
|
44
|
+
}
|
45
|
+
.datepicker table {
|
46
|
+
width: 100%;
|
47
|
+
margin: 0;
|
48
|
+
}
|
49
|
+
.datepicker td, .datepicker th {
|
50
|
+
text-align: center;
|
51
|
+
width: 20px;
|
52
|
+
height: 20px;
|
53
|
+
-webkit-border-radius: 4px;
|
54
|
+
-moz-border-radius: 4px;
|
55
|
+
border-radius: 4px;
|
56
|
+
}
|
57
|
+
.datepicker td.day:hover {
|
58
|
+
background: #eeeeee;
|
59
|
+
cursor: pointer;
|
60
|
+
}
|
61
|
+
.datepicker td.old, .datepicker td.new {
|
62
|
+
color: #999999;
|
63
|
+
}
|
64
|
+
.datepicker td.active, .datepicker td.active:hover {
|
65
|
+
background-color: #006dcc;
|
66
|
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
67
|
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
68
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
69
|
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
70
|
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
71
|
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
72
|
+
background-repeat: repeat-x;
|
73
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
74
|
+
border-color: #0044cc #0044cc #002a80;
|
75
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
76
|
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
77
|
+
color: #fff;
|
78
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
79
|
+
}
|
80
|
+
.datepicker td.active:hover,
|
81
|
+
.datepicker td.active:hover:hover,
|
82
|
+
.datepicker td.active:active,
|
83
|
+
.datepicker td.active:hover:active,
|
84
|
+
.datepicker td.active.active,
|
85
|
+
.datepicker td.active:hover.active,
|
86
|
+
.datepicker td.active.disabled,
|
87
|
+
.datepicker td.active:hover.disabled,
|
88
|
+
.datepicker td.active[disabled],
|
89
|
+
.datepicker td.active:hover[disabled] {
|
90
|
+
background-color: #0044cc;
|
91
|
+
}
|
92
|
+
.datepicker td.active:active,
|
93
|
+
.datepicker td.active:hover:active,
|
94
|
+
.datepicker td.active.active,
|
95
|
+
.datepicker td.active:hover.active {
|
96
|
+
background-color: #003399 \9;
|
97
|
+
}
|
98
|
+
.datepicker td span {
|
99
|
+
display: block;
|
100
|
+
width: 47px;
|
101
|
+
height: 54px;
|
102
|
+
line-height: 54px;
|
103
|
+
float: left;
|
104
|
+
margin: 2px;
|
105
|
+
cursor: pointer;
|
106
|
+
-webkit-border-radius: 4px;
|
107
|
+
-moz-border-radius: 4px;
|
108
|
+
border-radius: 4px;
|
109
|
+
}
|
110
|
+
.datepicker td span:hover {
|
111
|
+
background: #eeeeee;
|
112
|
+
}
|
113
|
+
.datepicker td span.active {
|
114
|
+
background-color: #006dcc;
|
115
|
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
116
|
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
117
|
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
118
|
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
119
|
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
120
|
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
121
|
+
background-repeat: repeat-x;
|
122
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
123
|
+
border-color: #0044cc #0044cc #002a80;
|
124
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
125
|
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
126
|
+
color: #fff;
|
127
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
128
|
+
}
|
129
|
+
.datepicker td span.active:hover,
|
130
|
+
.datepicker td span.active:active,
|
131
|
+
.datepicker td span.active.active,
|
132
|
+
.datepicker td span.active.disabled,
|
133
|
+
.datepicker td span.active[disabled] {
|
134
|
+
background-color: #0044cc;
|
135
|
+
}
|
136
|
+
.datepicker td span.active:active, .datepicker td span.active.active {
|
137
|
+
background-color: #003399 \9;
|
138
|
+
}
|
139
|
+
.datepicker td span.old {
|
140
|
+
color: #999999;
|
141
|
+
}
|
142
|
+
.datepicker th.switch {
|
143
|
+
width: 145px;
|
144
|
+
}
|
145
|
+
.datepicker thead tr:first-child th {
|
146
|
+
cursor: pointer;
|
147
|
+
}
|
148
|
+
.datepicker thead tr:first-child th:hover {
|
149
|
+
background: #eeeeee;
|
150
|
+
}
|
151
|
+
.input-append.date .add-on i, .input-prepend.date .add-on i {
|
152
|
+
display: block;
|
153
|
+
cursor: pointer;
|
154
|
+
width: 16px;
|
155
|
+
height: 16px;
|
156
|
+
}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
.bootstrap-timepicker.dropdown-menu {
|
2
|
+
border-radius: 4px 4px 4px 4px;
|
3
|
+
display: none;
|
4
|
+
left: 0;
|
5
|
+
margin-top: 1px;
|
6
|
+
padding: 4px;
|
7
|
+
top: 0;
|
8
|
+
min-width: 10px;
|
9
|
+
}
|
10
|
+
.bootstrap-timepicker.dropdown-menu.open {
|
11
|
+
display: inline-block;
|
12
|
+
}
|
13
|
+
.bootstrap-timepicker.dropdown-menu:before {
|
14
|
+
border-bottom: 7px solid rgba(0, 0, 0, 0.2);
|
15
|
+
border-left: 7px solid transparent;
|
16
|
+
border-right: 7px solid transparent;
|
17
|
+
content: "";
|
18
|
+
left: 6px;
|
19
|
+
position: absolute;
|
20
|
+
top: -7px;
|
21
|
+
}
|
22
|
+
.bootstrap-timepicker.dropdown-menu:after {
|
23
|
+
border-bottom: 6px solid #FFFFFF;
|
24
|
+
border-left: 6px solid transparent;
|
25
|
+
border-right: 6px solid transparent;
|
26
|
+
content: "";
|
27
|
+
left: 7px;
|
28
|
+
position: absolute;
|
29
|
+
top: -6px;
|
30
|
+
}
|
31
|
+
.bootstrap-timepicker.modal {
|
32
|
+
margin-left: -100px;
|
33
|
+
margin-top: 0;
|
34
|
+
top: 30%;
|
35
|
+
width: 200px;
|
36
|
+
}
|
37
|
+
.bootstrap-timepicker.modal .modal-content {
|
38
|
+
padding: 0;
|
39
|
+
}
|
40
|
+
.bootstrap-timepicker table {
|
41
|
+
margin: 0;
|
42
|
+
width: 100%;
|
43
|
+
}
|
44
|
+
.bootstrap-timepicker table td {
|
45
|
+
height: 30px;
|
46
|
+
margin: 0;
|
47
|
+
padding: 2px;
|
48
|
+
text-align: center;
|
49
|
+
}
|
50
|
+
.bootstrap-timepicker table td span {
|
51
|
+
width: 100%;
|
52
|
+
}
|
53
|
+
.bootstrap-timepicker table td a {
|
54
|
+
border: 1px solid transparent;
|
55
|
+
display: inline-block;
|
56
|
+
margin: 0;
|
57
|
+
outline: 0 none;
|
58
|
+
padding: 8px 0;
|
59
|
+
width: 3em;
|
60
|
+
}
|
61
|
+
.bootstrap-timepicker table td a:hover {
|
62
|
+
background-color: #EEEEEE;
|
63
|
+
border-color: #DDDDDD;
|
64
|
+
border-radius: 4px 4px 4px 4px;
|
65
|
+
}
|
66
|
+
.bootstrap-timepicker table td a i {
|
67
|
+
margin-top: 2px;
|
68
|
+
}
|
69
|
+
.bootstrap-timepicker table td input {
|
70
|
+
margin: 0;
|
71
|
+
text-align: center;
|
72
|
+
width: 25px;
|
73
|
+
}
|
74
|
+
.bootstrap-timepicker-component .add-on {
|
75
|
+
cursor: pointer;
|
76
|
+
}
|
77
|
+
.bootstrap-timepicker-component .add-on i {
|
78
|
+
display: block;
|
79
|
+
height: 16px;
|
80
|
+
width: 16px;
|
81
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/datetimepicker/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Daniel Ott"]
|
6
|
+
gem.email = ["danott@marshill.com"]
|
7
|
+
gem.description = %q{Custom field for individual setting of date and time for Rails :datetime attributes.}
|
8
|
+
gem.summary = %q{Custom field for individual setting of date and time for Rails :datetime attributes.}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "datetimepicker"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Datetimepicker::VERSION
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "datetimepicker/version"
|
2
|
+
|
3
|
+
module Datetimepicker
|
4
|
+
autoload :DateAndTimeManipulator, "datetimepicker/date_and_time_manipulator"
|
5
|
+
|
6
|
+
class Engine < ::Rails::Engine
|
7
|
+
require "datetimepicker/engine"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
require "datetimepicker/date_formats"
|
13
|
+
require "datetimepicker/activerecord"
|
14
|
+
require "datetimepicker/simple_form/inputs/datetimepicker_input"
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# Extension made to ActiveRecord::Base to handle datetimepickers dynamic methods.
|
2
|
+
ActiveRecord::Base.class_eval do
|
3
|
+
|
4
|
+
# Public: All the available :datetime columns for this model.
|
5
|
+
#
|
6
|
+
# Returns an Array of attribute names.
|
7
|
+
def self.datetime_columns
|
8
|
+
@datetime_columns ||= columns.select { |c| c.type == :datetime }.map(&:name)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public: we need to retain all of ActiveRecord's existing respond_to? fun.
|
12
|
+
alias_method :active_record_original_respond_to?, :respond_to?
|
13
|
+
|
14
|
+
# Public: ActiveRecord::Base should recognize our dynamic methods as existing.
|
15
|
+
#
|
16
|
+
# This respond_to? override will do exactly that. If the method being
|
17
|
+
# tested does not match any of these, the pre-exisiting respond_to? for
|
18
|
+
# ActiveRecord::Base is called to continue looking.
|
19
|
+
def respond_to?(method, include_private = false)
|
20
|
+
(method =~ datetimepicker_method_regex) || active_record_original_respond_to?(method, include_private)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Private: we need to retain all of ActiveRecord's existing method_missing fun.
|
26
|
+
alias_method :active_record_original_method_missing, :method_missing
|
27
|
+
|
28
|
+
# Private: handle missing methods for datetimepickers.
|
29
|
+
#
|
30
|
+
# This method_missing override will do exactly that. If the method being
|
31
|
+
# tested does not match any of these, the pre-exisiting method_missing for
|
32
|
+
# ActiveRecord::Base is called to continue looking
|
33
|
+
def method_missing(method, *args, &block)
|
34
|
+
if method =~ datetimepicker_method_regex
|
35
|
+
# First matched group in datetimepicker_method_regex is the attribute
|
36
|
+
# we're trying to set/get.
|
37
|
+
attribute_name = $1
|
38
|
+
|
39
|
+
# Second matched group in datetimepicker_method_regex is the method
|
40
|
+
# on datetimepicker that is trying to be sent.
|
41
|
+
# Possible values: "date", "date=", "time", "time=",
|
42
|
+
# "date_before_type_cast", "time_before_type_cast"
|
43
|
+
datetimepicker_method = $2
|
44
|
+
|
45
|
+
# When simple_form is generating inputs, it's looking for the value of
|
46
|
+
# "#{attribute_name}_datepicker_date_before_type_cast". Since this
|
47
|
+
# "column" we're generating inputs for is dynamic, we can cut that part
|
48
|
+
# out to keep things working the way we expect.
|
49
|
+
datetimepicker_method.gsub!("_before_type_cast", "")
|
50
|
+
|
51
|
+
send(:datetimepicker_proxy, attribute_name, datetimepicker_method, *args)
|
52
|
+
else
|
53
|
+
active_record_original_method_missing(method, *args, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Private: the regex that matches datetimepicker's dynamic methods.
|
58
|
+
#
|
59
|
+
# The method we want to allow to be called dynamically:
|
60
|
+
#
|
61
|
+
# - attribute_name_datetimepicker_date
|
62
|
+
# - attribute_name_datetimepicker_date=
|
63
|
+
# - attribute_name_datetimepicker_date_before_type_cast
|
64
|
+
# - attribute_name_datetimepicker_time
|
65
|
+
# - attribute_name_datetimepicker_time=
|
66
|
+
# - attribute_name_datetimepicker_time_before_type_cast
|
67
|
+
#
|
68
|
+
# Returns a Regex
|
69
|
+
def datetimepicker_method_regex
|
70
|
+
/^(\w+)_datetimepicker_((?:date|time)(?:_before_type_cast)?=?)$/
|
71
|
+
end
|
72
|
+
|
73
|
+
# Private: does a datetime column exist for this attribute_name?
|
74
|
+
#
|
75
|
+
# attribute_name - the column we're testing for.
|
76
|
+
#
|
77
|
+
# Returns a Boolean.
|
78
|
+
def datetimepicker_column?(attribute_name)
|
79
|
+
self.class.datetime_columns.include?(attribute_name.to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Private: Proxy method written so we can utilize dynamic methods for
|
83
|
+
# manipulating columns of type datetime by their date and time independently.
|
84
|
+
#
|
85
|
+
# Getters get date/time values.
|
86
|
+
#
|
87
|
+
# Setters set date/time values, and update the datetime column.
|
88
|
+
#
|
89
|
+
# attribute_name - The active record attribute we're wrapping.
|
90
|
+
# datetimepicker_method - the message to pass along to manipulate the column
|
91
|
+
# using the Datetimepicker.
|
92
|
+
# args - Any attitional arguments to pass along to
|
93
|
+
# Datetimepicker.
|
94
|
+
#
|
95
|
+
# Examples
|
96
|
+
#
|
97
|
+
# datetimepicker_proxy(:created_at, "date=", "2012/01/01")
|
98
|
+
#
|
99
|
+
# Returns mixed. Getters return gotten value. Setters return the new
|
100
|
+
# attribute_name value.
|
101
|
+
def datetimepicker_proxy(attribute_name, datetimepicker_method, *args)
|
102
|
+
if !datetimepicker_column?(attribute_name)
|
103
|
+
raise "Datetimepicker can only be used on columns of type :datetime"
|
104
|
+
end
|
105
|
+
|
106
|
+
# Datetimepicker won't work so good with a nil value.
|
107
|
+
attribute_value = send(attribute_name) || Time.now.beginning_of_hour
|
108
|
+
|
109
|
+
datetimepicker = Datetimepicker::DateAndTimeManipulator.new(attribute_value,
|
110
|
+
Time::DATE_FORMATS[:datetimepicker_date],
|
111
|
+
Time::DATE_FORMATS[:datetimepicker_time])
|
112
|
+
return_value = datetimepicker.send(datetimepicker_method, *args)
|
113
|
+
|
114
|
+
# Setters gonna set.
|
115
|
+
if datetimepicker_method =~ /=$/
|
116
|
+
return_value = write_attribute(attribute_name.to_sym, datetimepicker.datetime)
|
117
|
+
end
|
118
|
+
|
119
|
+
return_value
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Public: A simple structure for independently manipulating the date and time
|
2
|
+
# components of a TimeWithZone object, while maintining the the existing date
|
3
|
+
# and time information.
|
4
|
+
#
|
5
|
+
# datetime - an instance of DateTime/Time/TimeWithZone.
|
6
|
+
# date_format - A String containing the strftime format for setting/getting
|
7
|
+
# date component of datetime.
|
8
|
+
# time_format - A String containing the strftime format for setting/getting
|
9
|
+
# time component of datetime.
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# DateTimePicker.new(Post.first.created_at, "%Y/%m/%d", "%H:%M")
|
13
|
+
module Datetimepicker
|
14
|
+
class DateAndTimeManipulator < Struct.new(:datetime, :date_format, :time_format)
|
15
|
+
|
16
|
+
# Public: get the date component of datetime.
|
17
|
+
#
|
18
|
+
# Returns a String in the format of date_format.
|
19
|
+
def date
|
20
|
+
datetime.strftime(date_format)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: set the date component of datetime.
|
24
|
+
#
|
25
|
+
# new_date - The String representation of date component for datetime.
|
26
|
+
# The String should be in the format of date_format.
|
27
|
+
def date=(new_date)
|
28
|
+
self.datetime = parse_date_and_time(new_date, time)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: get the time component of datetime.
|
32
|
+
#
|
33
|
+
# Returns a String in the format of time_format.
|
34
|
+
def time
|
35
|
+
datetime.strftime(time_format)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: set the time component of datetime.
|
39
|
+
#
|
40
|
+
# new_time - The String representation of time component for datetime.
|
41
|
+
# The String should be in the format of time_format.
|
42
|
+
def time=(new_time)
|
43
|
+
self.datetime = parse_date_and_time(date, new_time)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Private: create a new TimeWithZone from date and time Strings.
|
49
|
+
#
|
50
|
+
# date - A String of the date in the format of date_format
|
51
|
+
# time - A String of the time in the format of time_format.
|
52
|
+
#
|
53
|
+
# The following blog post was infinitely valuable in figuring out how to
|
54
|
+
# parse dates and times while maintaining a time zone in Rails.
|
55
|
+
#
|
56
|
+
# http://www.elabs.se/blog/36-working-with-time-zones-in-ruby-on-rails
|
57
|
+
#
|
58
|
+
# Returns an instance of TimeWithZone.
|
59
|
+
def parse_date_and_time(parse_date, parse_time)
|
60
|
+
Time.strptime(date_and_time_format(parse_date, parse_time),
|
61
|
+
date_and_time_format(date_format, time_format)).in_time_zone(Time.zone)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Private: generate strings for parsing datetime in a consistent way.
|
65
|
+
#
|
66
|
+
# date_component - A String of the date component of the date and time pair.
|
67
|
+
# time_component - A String of the time component of the date and time pair.
|
68
|
+
# separator - (optional) String used to concatenate the components.
|
69
|
+
#
|
70
|
+
# Examples
|
71
|
+
#
|
72
|
+
# date_and_time_format("%Y/%m/%d", "%H:%M")
|
73
|
+
# => "%Y/%m/%d %H:%M"
|
74
|
+
#
|
75
|
+
# date_and_time_format("2004/08/15", "16:23", "T")
|
76
|
+
# => "2004/0815T16:23"
|
77
|
+
#
|
78
|
+
# Returns a String.
|
79
|
+
def date_and_time_format(date_component, time_component, separator = " ")
|
80
|
+
"#{date_component}#{separator}#{time_component}"
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|