phpf 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +22 -0
- data/README.html +61 -0
- data/Rakefile.rb +40 -0
- data/lib/phpf.rb +42 -0
- data/lib/phpf/evaluation.rb +55 -0
- data/lib/phpf/tests.rb +93 -0
- data/lib/phpf/tokenizing.rb +37 -0
- data/lib/phpf/translations.rb +244 -0
- metadata +61 -0
data/COPYING.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Tim Fletcher <tfletcher.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.html
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>phpf</title>
|
4
|
+
<style type="text/css" media="screen">
|
5
|
+
html {
|
6
|
+
height: 100%;
|
7
|
+
margin-bottom: 1px;
|
8
|
+
}
|
9
|
+
body {
|
10
|
+
margin: 0;
|
11
|
+
padding: 30px;
|
12
|
+
}
|
13
|
+
h1, h2 {
|
14
|
+
font-family: Garamond, Rockwell, serif;
|
15
|
+
}
|
16
|
+
h2 {
|
17
|
+
margin-top: 1.5em;
|
18
|
+
}
|
19
|
+
code {
|
20
|
+
font-family: "Panic Sans", "Bitstream Vera Sans Mono", Consolas, Monaco, monospace;
|
21
|
+
font-size: 11px;
|
22
|
+
}
|
23
|
+
</style>
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
|
27
|
+
|
28
|
+
<h1>phpf <small>1.0.0</small></h1>
|
29
|
+
|
30
|
+
<p>A <a href="http://www.ruby-lang.org/">Ruby</a> port of <a href="http://www.php.net/date">PHP’s date function</a>.</p>
|
31
|
+
|
32
|
+
|
33
|
+
<h2>HOWTO get it</h2>
|
34
|
+
|
35
|
+
<p>Use <a href="http://rubygems.org/">RubyGems</a> (<tt>gem install phpf</tt>),
|
36
|
+
or <a href="http://rubyforge.org/frs/?group_id=5524">download from RubyForge</a>.</p>
|
37
|
+
|
38
|
+
|
39
|
+
<h2>HOWTO use it</h2>
|
40
|
+
|
41
|
+
<p>Either use Time#phpf, or Kernel#date, e.g.</p>
|
42
|
+
|
43
|
+
<pre><code>require 'phpf'
|
44
|
+
|
45
|
+
time = Time.parse('1/1/2008 12:34:56')
|
46
|
+
|
47
|
+
time.phpf('jS F Y H:i') # => "1st January 2008 12:34"
|
48
|
+
|
49
|
+
time.to_i # => 1199190896
|
50
|
+
|
51
|
+
date('jS F Y H:i', 1199190896) # => "1st January 2008 12:34"
|
52
|
+
</code></pre>
|
53
|
+
|
54
|
+
|
55
|
+
<h2>See Also</h2>
|
56
|
+
|
57
|
+
<p><a href="http://simonwillison.net/2003/Oct/7/dateInPython/">PHP’s date() function in Python</a></p>
|
58
|
+
|
59
|
+
|
60
|
+
</body>
|
61
|
+
</html>
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
|
6
|
+
GEMSPEC = Gem::Specification.new do |s|
|
7
|
+
s.name = 'phpf'
|
8
|
+
s.version = '1.0.0'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.has_rdoc = false
|
11
|
+
s.summary = "Port of PHP's date function."
|
12
|
+
s.description = s.summary
|
13
|
+
s.author = 'Tim Fletcher'
|
14
|
+
s.email = 'twoggle@gmail.com'
|
15
|
+
s.homepage = 'http://phpf.rubyforge.org/'
|
16
|
+
s.files = Dir.glob('lib/**/*') + %w( COPYING.txt Rakefile.rb README.html )
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::GemPackageTask.new(GEMSPEC) { }
|
21
|
+
|
22
|
+
Rake::PackageTask.new(GEMSPEC.name, GEMSPEC.version) do |p|
|
23
|
+
p.need_tar_gz = true
|
24
|
+
p.package_files.include GEMSPEC.files
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Run all the tests'
|
28
|
+
task :test do
|
29
|
+
if ARGV.length == 2 && ARGV.last =~ /SYM=(.)/
|
30
|
+
TEST_SYMBOL = $1.to_sym
|
31
|
+
end
|
32
|
+
require 'test/unit'
|
33
|
+
Test::Unit.run = false
|
34
|
+
$:.unshift 'lib'
|
35
|
+
require 'phpf/tests'
|
36
|
+
Test::Unit::AutoRunner.run
|
37
|
+
$SKIPPED_PHP_CHECKS.each do |format, version|
|
38
|
+
puts "- skipped check for %s (requires PHP %s)" % [format, version]
|
39
|
+
end
|
40
|
+
end
|
data/lib/phpf.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'phpf/tokenizing'
|
2
|
+
require 'phpf/evaluation'
|
3
|
+
require 'phpf/translations'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module PHPF
|
7
|
+
def self.format(string)
|
8
|
+
Symbol === string ? StandardFormats.const_get(string.to_s.upcase) : string
|
9
|
+
end
|
10
|
+
|
11
|
+
# cf. http://uk3.php.net/manual/en/ref.datetime.php#datetime.constants
|
12
|
+
#
|
13
|
+
# DATE_RFC822/DATE_COOKIE/DATE_RFC1123/DATE_RSS, DATE_ISO8601,
|
14
|
+
# and DATE_RFC2822 all have equivalent Ruby methods.
|
15
|
+
#
|
16
|
+
module StandardFormats
|
17
|
+
RFC850, RFC1036 = "l, d-M-y H:i:s T".freeze
|
18
|
+
|
19
|
+
RFC3339, W3C, ATOM = "Y-m-d\TH:i:sP".freeze
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Time
|
24
|
+
def self.epoch
|
25
|
+
@@epoch ||= parse('1st Jan 1970 00:00:00 UTC').freeze
|
26
|
+
end
|
27
|
+
def phpf(string)
|
28
|
+
PHPF.evaluate(PHPF.tokenize(PHPF.format(string)), self).join
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Integer
|
33
|
+
def to_time
|
34
|
+
Time.epoch + self
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Kernel
|
39
|
+
def date(format_string, time = Time.now)
|
40
|
+
time.to_i.to_time.phpf(format_string)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module PHPF
|
2
|
+
def self.evaluate(tokens, time)
|
3
|
+
tokens.map do |token|
|
4
|
+
translations.has_key?(token) ? call(translations[token], time) : token
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def self.translate(symbol, &rule)
|
11
|
+
translations[@last_symbol = symbol] = rule
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.only(php_version)
|
15
|
+
php_version_requirements[@last_symbol] = php_version
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.test(time_string, expected_output)
|
19
|
+
test_cases[@last_symbol] << [time_string, expected_output]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.translations
|
23
|
+
@translations ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.call(translation, time)
|
27
|
+
translation.arity == 1 ? translation.call(time) : time.instance_eval(&translation)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.test_cases
|
31
|
+
@test_cases ||= Hash.new { |h, k| h[k] = [] }
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.php_version_requirements
|
35
|
+
@php_version_requirements ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.epoch
|
39
|
+
'1st Jan 1970 00:00:00 UTC'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.ordinal(n)
|
43
|
+
return 'th' if (11..13).include?(n % 100)
|
44
|
+
case n % 10
|
45
|
+
when 1: 'st'
|
46
|
+
when 2: 'nd'
|
47
|
+
when 3: 'rd'
|
48
|
+
else 'th'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.date(time)
|
53
|
+
Date.new(time.year, time.month, time.mday)
|
54
|
+
end
|
55
|
+
end
|
data/lib/phpf/tests.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'phpf'
|
3
|
+
|
4
|
+
$SKIPPED_PHP_CHECKS = {}
|
5
|
+
|
6
|
+
module PHPF
|
7
|
+
class Tests < Test::Unit::TestCase
|
8
|
+
class VersionString
|
9
|
+
def initialize(string)
|
10
|
+
@string = string.to_s
|
11
|
+
end
|
12
|
+
def to_s
|
13
|
+
@string
|
14
|
+
end
|
15
|
+
def <=>(v)
|
16
|
+
@string.split('.') <=> v.to_s.split('.')
|
17
|
+
end
|
18
|
+
include Comparable
|
19
|
+
end
|
20
|
+
|
21
|
+
unless defined?(PHP)
|
22
|
+
PHP = 'php'
|
23
|
+
end
|
24
|
+
|
25
|
+
PHP_VERSION = begin
|
26
|
+
(output = `#{PHP} -version`).empty? ? nil : VersionString.new(output[/(\d\.\d\.\d)/, 1])
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_expected_php_output(string, tokens, time)
|
30
|
+
php_code = 'echo date(%p, %d);' % [ PHPF.untokenize(tokens), time.to_i ]
|
31
|
+
php_output = `#{PHP} -r #{php_code.inspect}`
|
32
|
+
|
33
|
+
assert_equal string, php_output, "unexpected PHP output: from %p" % php_code
|
34
|
+
end
|
35
|
+
|
36
|
+
def required_version(tokens)
|
37
|
+
tokens.inject(nil) do |v, token|
|
38
|
+
next v unless token.is_a?(Symbol)
|
39
|
+
next v unless PHPF.php_version_requirements.has_key?(token)
|
40
|
+
version = VersionString.new(PHPF.php_version_requirements[token])
|
41
|
+
v.nil?? version : (v > version ? v : version)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_evaluates_to(string, format, time_string)
|
46
|
+
tokens = case format
|
47
|
+
when String then
|
48
|
+
tokens = PHPF.tokenize(format)
|
49
|
+
assert_equal format, PHPF.untokenize(tokens)
|
50
|
+
tokens
|
51
|
+
when Symbol then [format]
|
52
|
+
when Array then format
|
53
|
+
end
|
54
|
+
|
55
|
+
time = Time.parse(time_string)
|
56
|
+
|
57
|
+
unless PHP_VERSION.nil?
|
58
|
+
if (required_version = required_version(tokens)).nil?
|
59
|
+
assert_expected_php_output string, tokens, time
|
60
|
+
elsif PHP_VERSION >= required_version
|
61
|
+
assert_expected_php_output string, tokens, time
|
62
|
+
else
|
63
|
+
$SKIPPED_PHP_CHECKS[format] = required_version
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
assert_equal string, PHPF.evaluate(tokens, time).to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
PHPF.test_cases.each do |symbol, test_cases|
|
71
|
+
if !defined?(TEST_SYMBOL) || TEST_SYMBOL == symbol
|
72
|
+
define_method("test_evaluate_#{symbol}") do
|
73
|
+
test_cases.each do |(time_string, expected_output)|
|
74
|
+
assert_evaluates_to expected_output, symbol.to_s, time_string
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_php_examples # cf. http://php.net/date (Example #4)
|
81
|
+
time = Time.parse('March 10th, 2001, 5:16:18 pm')
|
82
|
+
|
83
|
+
assert_equal 'March 10, 2001, 5:16 pm', time.phpf('F j, Y, g:i a')
|
84
|
+
assert_equal '03.10.01', time.phpf('m.d.y')
|
85
|
+
assert_equal '10, 3, 2001', time.phpf('j, n, Y')
|
86
|
+
assert_equal '20010310', time.phpf('Ymd')
|
87
|
+
assert_equal '05-16-18, 10-03-01, 1631 1618 6 Satpm01', time.phpf('h-i-s, j-m-y, it is w Day')
|
88
|
+
assert_equal 'it is the 10th day.', time.phpf('\i\t \i\s \t\h\e jS \d\a\y.')
|
89
|
+
assert_equal '17:03:18 m is month', time.phpf('H:m:s \m \i\s \m\o\n\t\h')
|
90
|
+
assert_equal '17:16:18', time.phpf('H:i:s')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module PHPF
|
2
|
+
FormatCharacters = 'dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU'
|
3
|
+
|
4
|
+
def self.tokenize(format_string)
|
5
|
+
tokens = []
|
6
|
+
until format_string.empty?
|
7
|
+
case format_string
|
8
|
+
when /^([#{FormatCharacters}])/
|
9
|
+
tokens << $1.to_sym
|
10
|
+
when /^\\([#{FormatCharacters}])/
|
11
|
+
tokens << $1
|
12
|
+
when /^([^\\#{FormatCharacters}]+?)(?=[\\#{FormatCharacters}])/
|
13
|
+
tokens << $1
|
14
|
+
when /^([^\\#{FormatCharacters}]+?)$/
|
15
|
+
tokens << $1
|
16
|
+
else
|
17
|
+
raise 'cannot tokenize format string: %p' % format_string
|
18
|
+
end
|
19
|
+
format_string = $'
|
20
|
+
end
|
21
|
+
return tokens
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.untokenize(tokens)
|
25
|
+
tokens.map { |token| untok(token, token.to_s) }.join
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.untok(token, string)
|
31
|
+
if Symbol === token
|
32
|
+
return string
|
33
|
+
else
|
34
|
+
FormatCharacters.include?(string) ? '\\' + string : string
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
# cf. http://php.net/date
|
4
|
+
#
|
5
|
+
module PHPF
|
6
|
+
|
7
|
+
# d: Day of the month, 2 digits with leading zeros (e.g. 01 to 31)
|
8
|
+
#
|
9
|
+
translate(:d) { '%02d' % mday }
|
10
|
+
test '1st', '01'
|
11
|
+
test '23rd', '23'
|
12
|
+
|
13
|
+
# D: A textual representation of a day, three letters (e.g. Mon through Sun)
|
14
|
+
#
|
15
|
+
translate(:D) { Time::RFC2822_DAY_NAME[wday] }
|
16
|
+
test '9th Dec 2007', 'Sun'
|
17
|
+
|
18
|
+
# j: Day of the month without leading zeros (e.g. 1 to 31)
|
19
|
+
#
|
20
|
+
translate(:j) { mday }
|
21
|
+
test '1st', '1'
|
22
|
+
test '23rd', '23'
|
23
|
+
|
24
|
+
# l: A full textual representation of the day of the week
|
25
|
+
# e.g. Sunday through Saturday
|
26
|
+
#
|
27
|
+
translate(:l) { strftime('%A') }
|
28
|
+
test '9th Dec 2007', 'Sunday'
|
29
|
+
|
30
|
+
# N: ISO-8601 numeric representation of the day of the week
|
31
|
+
# e.g. 1 [for Monday] through 7 [for Sunday]
|
32
|
+
#
|
33
|
+
translate(:N) { |time| date(time).cwday }
|
34
|
+
only '5.1.0'
|
35
|
+
test '9th Dec 2007', '7'
|
36
|
+
test '10th Dec 2007', '1'
|
37
|
+
|
38
|
+
# S: English ordinal suffix for the day of the month
|
39
|
+
# e.g. st, nd, rd or th
|
40
|
+
#
|
41
|
+
translate(:S) { |time| ordinal(time.day) }
|
42
|
+
test '1st', 'st'
|
43
|
+
test '2nd', 'nd'
|
44
|
+
test '3rd', 'rd'
|
45
|
+
test '4th', 'th'
|
46
|
+
|
47
|
+
# w: Numeric representation of the day of the week
|
48
|
+
# e.g. 0 [for Sunday] through 6 [for Saturday]
|
49
|
+
#
|
50
|
+
translate(:w) { wday }
|
51
|
+
test '9th Dec 2007', '0'
|
52
|
+
test '10th Dec 2007', '1'
|
53
|
+
|
54
|
+
# z: The day of the year (starting from 0)
|
55
|
+
# e.g. 0 through 365
|
56
|
+
#
|
57
|
+
translate(:z) { yday - 1 }
|
58
|
+
test '1st Jan 2007', '0'
|
59
|
+
test '31st Dec 2007', '364'
|
60
|
+
test '31st Dec 2008', '365'
|
61
|
+
|
62
|
+
# W: ISO-8601 week number of year, weeks starting on Monday
|
63
|
+
# e.g. 42 [for the 42nd week in the year]
|
64
|
+
#
|
65
|
+
translate(:W) { |time| '%02d' % date(time).cweek }
|
66
|
+
test '24th Dec 2007 12:00', '52'
|
67
|
+
test '31st Dec 2007 12:00', '01'
|
68
|
+
test ' 1st Jan 2008 12:00', '01'
|
69
|
+
test ' 8th Jan 2008 12:00', '02'
|
70
|
+
|
71
|
+
# F: A full textual representation of a month (January through December)
|
72
|
+
#
|
73
|
+
translate(:F) { strftime('%B') }
|
74
|
+
test 'Jan', 'January'
|
75
|
+
test 'Dec', 'December'
|
76
|
+
|
77
|
+
# m: Numeric representation of a month, with leading zeros
|
78
|
+
# e.g. 01 through 12
|
79
|
+
#
|
80
|
+
translate(:m) { '%02d' % month }
|
81
|
+
test 'Jan', '01'
|
82
|
+
test 'Dec', '12'
|
83
|
+
|
84
|
+
# M: A short textual representation of a month
|
85
|
+
# e.g. Jan through Dec
|
86
|
+
#
|
87
|
+
translate(:M) { Time::RFC2822_MONTH_NAME[month - 1] }
|
88
|
+
test 'Jan', 'Jan'
|
89
|
+
test 'Dec', 'Dec'
|
90
|
+
|
91
|
+
# n: Numeric representation of a month, without leading zeros
|
92
|
+
# e.g. 1 through 12
|
93
|
+
#
|
94
|
+
translate(:n) { month }
|
95
|
+
test 'Jan', '1'
|
96
|
+
test 'Dec', '12'
|
97
|
+
|
98
|
+
# t: Number of days in the given month (28 through 31)
|
99
|
+
#
|
100
|
+
translate(:t) { |time| ((date(time) >> 1) - time.mday).day }
|
101
|
+
test 'Jan 2007', '31'
|
102
|
+
test 'Feb 2007', '28'
|
103
|
+
test 'Feb 2008', '29'
|
104
|
+
|
105
|
+
# L: 1 if it is a leap year, 0 otherwise
|
106
|
+
#
|
107
|
+
translate(:L) { Date.leap?(year) ? 1 : 0 }
|
108
|
+
test 'Jan 2007', '0'
|
109
|
+
test 'Jan 2008', '1'
|
110
|
+
|
111
|
+
# o: ISO-8601 year number. This has the same value as Y,
|
112
|
+
# except that if the ISO week number (W) belongs to the previous
|
113
|
+
# or next year, that year is used instead.
|
114
|
+
#
|
115
|
+
translate(:o) { |time| date(time).cwyear }
|
116
|
+
only '5.1.0'
|
117
|
+
test '24th Dec 2007 12:00', '2007'
|
118
|
+
test '31st Dec 2007 12:00', '2008'
|
119
|
+
test ' 1st Jan 2008 12:00', '2008'
|
120
|
+
test ' 8th Jan 2008 12:00', '2008'
|
121
|
+
|
122
|
+
# Y: A full numeric representation of a year
|
123
|
+
# e.g. 1999
|
124
|
+
#
|
125
|
+
translate(:Y) { year }
|
126
|
+
test 'Jan 1999', '1999'
|
127
|
+
|
128
|
+
# y: A two digit representation of a year
|
129
|
+
# e.g. 99 or 03
|
130
|
+
#
|
131
|
+
translate(:y) { strftime('%y') }
|
132
|
+
test 'Jan 1999', '99'
|
133
|
+
|
134
|
+
# a: Lowercase Ante meridiem and Post meridiem (am or pm)
|
135
|
+
#
|
136
|
+
translate(:a) { strftime('%p').downcase }
|
137
|
+
test '00:42', 'am'
|
138
|
+
test '12:42', 'pm'
|
139
|
+
|
140
|
+
# A: Uppercase Ante meridiem and Post meridiem (AM or PM)
|
141
|
+
#
|
142
|
+
translate(:A) { strftime('%p') }
|
143
|
+
test '00:42', 'AM'
|
144
|
+
test '12:42', 'PM'
|
145
|
+
|
146
|
+
# B: Swatch Internet time (000 through 999)
|
147
|
+
# cf. http://www.ypass.net/crap/internettime/
|
148
|
+
#
|
149
|
+
translate(:B) { '%03d' % (((utc.to_i + 3600) % 86400) / 86.4) }
|
150
|
+
test '1st Jan 2008 00:00:00 UTC', '041'
|
151
|
+
|
152
|
+
# g: 12-hour format of an hour without leading zeros (1 through 12)
|
153
|
+
#
|
154
|
+
translate(:g) { strftime('%I').to_i }
|
155
|
+
test '00:42', '12'
|
156
|
+
test '06:42', '6'
|
157
|
+
test '12:42', '12'
|
158
|
+
test '18:42', '6'
|
159
|
+
|
160
|
+
# G: 24-hour format of an hour without leading zeros (0 through 23)
|
161
|
+
#
|
162
|
+
translate(:G) { hour }
|
163
|
+
test '00:42', '0'
|
164
|
+
test '06:42', '6'
|
165
|
+
test '12:42', '12'
|
166
|
+
test '18:42', '18'
|
167
|
+
|
168
|
+
# h: 12-hour format of an hour with leading zeros (01 through 12)
|
169
|
+
#
|
170
|
+
translate(:h) { strftime('%I') }
|
171
|
+
test '00:42', '12'
|
172
|
+
test '06:42', '06'
|
173
|
+
test '12:42', '12'
|
174
|
+
test '18:42', '06'
|
175
|
+
|
176
|
+
# H: 24-hour format of an hour with leading zeros (00 through 23)
|
177
|
+
#
|
178
|
+
translate(:H) { strftime('%H') }
|
179
|
+
test '00:42', '00'
|
180
|
+
test '06:42', '06'
|
181
|
+
test '12:42', '12'
|
182
|
+
test '18:42', '18'
|
183
|
+
|
184
|
+
# i: Minutes with leading zeros (00 to 59)
|
185
|
+
#
|
186
|
+
translate(:i) { strftime('%M') }
|
187
|
+
test '00:00', '00'
|
188
|
+
test '00:12', '12'
|
189
|
+
|
190
|
+
# s: Seconds, with leading zeros (00 through 59)
|
191
|
+
#
|
192
|
+
translate(:s) { strftime('%S') }
|
193
|
+
test '00:00:00', '00'
|
194
|
+
test '00:00:12', '12'
|
195
|
+
|
196
|
+
# e: Timezone identifier
|
197
|
+
# e.g. UTC, GMT, Atlantic/Azores
|
198
|
+
#
|
199
|
+
# TODO
|
200
|
+
|
201
|
+
# O: Difference to Greenwich time (GMT) in hours
|
202
|
+
# e.g. +0200
|
203
|
+
#
|
204
|
+
# translate(:O) { '+%03d00' % (gmt_offset / 3600) }
|
205
|
+
# TODO
|
206
|
+
|
207
|
+
# P: Difference to Greenwich time (GMT) with colon between hours and minutes
|
208
|
+
# e.g. +02:00
|
209
|
+
#
|
210
|
+
# only '5.1.3'
|
211
|
+
# TODO
|
212
|
+
|
213
|
+
# T: Timezone abbreviation
|
214
|
+
# e.g. EST, MDT
|
215
|
+
#
|
216
|
+
# TODO
|
217
|
+
|
218
|
+
# Z: Timezone offset in seconds. The offset for timezones west of UTC
|
219
|
+
# is always negative, and for those east of UTC is always positive.
|
220
|
+
# e.g. -43200 through 50400
|
221
|
+
#
|
222
|
+
# TODO
|
223
|
+
|
224
|
+
# c: ISO 8601 date
|
225
|
+
# e.g. 2004-02-12T15:19:21+00:00
|
226
|
+
#
|
227
|
+
translate(:c) { iso8601.sub(/Z$/, '+00:00') }
|
228
|
+
only '5'
|
229
|
+
test '1st Jan 2008 00:00:00 UTC', '2008-01-01T00:00:00+00:00'
|
230
|
+
test '1st Jan 2008 12:34:56 PST', '2008-01-01T20:34:56+00:00'
|
231
|
+
|
232
|
+
# r: RFC 2822 formatted date
|
233
|
+
# e.g. Thu, 21 Dec 2000 16:01:07 +0200
|
234
|
+
#
|
235
|
+
translate(:r) { rfc2822 }
|
236
|
+
test '1st Jan 2008 00:00:00 GMT', 'Tue, 01 Jan 2008 00:00:00 +0000'
|
237
|
+
|
238
|
+
# U: Seconds since the Unix Epoch
|
239
|
+
#
|
240
|
+
translate(:U) { to_i }
|
241
|
+
test epoch, '0'
|
242
|
+
test '1st Jan 2008 00:00:00 UTC', '1199145600'
|
243
|
+
|
244
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: phpf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Fletcher
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-14 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Port of PHP's date function.
|
17
|
+
email: twoggle@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- lib/phpf
|
26
|
+
- lib/phpf/evaluation.rb
|
27
|
+
- lib/phpf/tests.rb
|
28
|
+
- lib/phpf/tokenizing.rb
|
29
|
+
- lib/phpf/translations.rb
|
30
|
+
- lib/phpf.rb
|
31
|
+
- COPYING.txt
|
32
|
+
- Rakefile.rb
|
33
|
+
- README.html
|
34
|
+
has_rdoc: false
|
35
|
+
homepage: http://phpf.rubyforge.org/
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.0.1
|
57
|
+
signing_key:
|
58
|
+
specification_version: 2
|
59
|
+
summary: Port of PHP's date function.
|
60
|
+
test_files: []
|
61
|
+
|