phpf 1.0.0
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/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
|
+
|