activerecord-jdbc-adapter-ficoh 1.3.21-java
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.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +462 -0
- data/.yardopts +4 -0
- data/Appraisals +36 -0
- data/CONTRIBUTING.md +49 -0
- data/Gemfile +68 -0
- data/History.md +1191 -0
- data/LICENSE.txt +25 -0
- data/README.md +277 -0
- data/RUNNING_TESTS.md +88 -0
- data/Rakefile +298 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +63 -0
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +1 -0
- data/lib/arel/visitors/compat.rb +64 -0
- data/lib/arel/visitors/db2.rb +137 -0
- data/lib/arel/visitors/derby.rb +112 -0
- data/lib/arel/visitors/firebird.rb +79 -0
- data/lib/arel/visitors/h2.rb +25 -0
- data/lib/arel/visitors/hsqldb.rb +32 -0
- data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
- data/lib/arel/visitors/sql_server.rb +225 -0
- data/lib/arel/visitors/sql_server/ng42.rb +293 -0
- data/lib/arjdbc.rb +22 -0
- data/lib/arjdbc/db2.rb +4 -0
- data/lib/arjdbc/db2/adapter.rb +802 -0
- data/lib/arjdbc/db2/as400.rb +137 -0
- data/lib/arjdbc/db2/column.rb +177 -0
- data/lib/arjdbc/db2/connection_methods.rb +45 -0
- data/lib/arjdbc/derby.rb +3 -0
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +567 -0
- data/lib/arjdbc/derby/connection_methods.rb +16 -0
- data/lib/arjdbc/derby/schema_creation.rb +15 -0
- data/lib/arjdbc/discover.rb +104 -0
- data/lib/arjdbc/firebird.rb +4 -0
- data/lib/arjdbc/firebird/adapter.rb +468 -0
- data/lib/arjdbc/firebird/connection_methods.rb +20 -0
- data/lib/arjdbc/h2.rb +3 -0
- data/lib/arjdbc/h2/adapter.rb +335 -0
- data/lib/arjdbc/h2/connection_methods.rb +22 -0
- data/lib/arjdbc/hsqldb.rb +3 -0
- data/lib/arjdbc/hsqldb/adapter.rb +304 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +23 -0
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
- data/lib/arjdbc/informix.rb +5 -0
- data/lib/arjdbc/informix/adapter.rb +160 -0
- data/lib/arjdbc/informix/connection_methods.rb +9 -0
- data/lib/arjdbc/jdbc.rb +62 -0
- data/lib/arjdbc/jdbc/adapter.rb +997 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/arel_support.rb +149 -0
- data/lib/arjdbc/jdbc/base_ext.rb +34 -0
- data/lib/arjdbc/jdbc/callbacks.rb +52 -0
- data/lib/arjdbc/jdbc/column.rb +83 -0
- data/lib/arjdbc/jdbc/connection.rb +26 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +59 -0
- data/lib/arjdbc/jdbc/driver.rb +44 -0
- data/lib/arjdbc/jdbc/error.rb +75 -0
- data/lib/arjdbc/jdbc/extension.rb +69 -0
- data/lib/arjdbc/jdbc/java.rb +13 -0
- data/lib/arjdbc/jdbc/type_cast.rb +154 -0
- data/lib/arjdbc/jdbc/type_converter.rb +142 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +822 -0
- data/lib/arjdbc/mssql/column.rb +207 -0
- data/lib/arjdbc/mssql/connection_methods.rb +72 -0
- data/lib/arjdbc/mssql/explain_support.rb +99 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/types.rb +343 -0
- data/lib/arjdbc/mssql/utils.rb +82 -0
- data/lib/arjdbc/mysql.rb +3 -0
- data/lib/arjdbc/mysql/adapter.rb +998 -0
- data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
- data/lib/arjdbc/mysql/column.rb +167 -0
- data/lib/arjdbc/mysql/connection_methods.rb +137 -0
- data/lib/arjdbc/mysql/explain_support.rb +82 -0
- data/lib/arjdbc/mysql/schema_creation.rb +58 -0
- data/lib/arjdbc/oracle.rb +4 -0
- data/lib/arjdbc/oracle/adapter.rb +968 -0
- data/lib/arjdbc/oracle/column.rb +136 -0
- data/lib/arjdbc/oracle/connection_methods.rb +21 -0
- data/lib/arjdbc/postgresql.rb +3 -0
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
- data/lib/arjdbc/postgresql/adapter.rb +1498 -0
- data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/oid.rb +412 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +132 -0
- data/lib/arjdbc/postgresql/column.rb +640 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +44 -0
- data/lib/arjdbc/postgresql/explain_support.rb +53 -0
- data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
- data/lib/arjdbc/postgresql/oid_types.rb +265 -0
- data/lib/arjdbc/postgresql/schema_creation.rb +60 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +3 -0
- data/lib/arjdbc/sqlite3/adapter.rb +654 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +36 -0
- data/lib/arjdbc/sqlite3/explain_support.rb +29 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +47 -0
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +66 -0
- data/lib/arjdbc/tasks/databases.rake +91 -0
- data/lib/arjdbc/tasks/databases3.rake +239 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
- data/lib/arjdbc/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/serialized_attributes.rb +98 -0
- data/lib/arjdbc/util/table_copier.rb +108 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +17 -0
- data/pom.xml +285 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
- data/rakelib/01-tomcat.rake +51 -0
- data/rakelib/02-test.rake +151 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/db.rake +58 -0
- data/rakelib/rails.rake +77 -0
- data/src/java/arjdbc/ArJdbcModule.java +288 -0
- data/src/java/arjdbc/db2/DB2Module.java +77 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +128 -0
- data/src/java/arjdbc/derby/DerbyModule.java +180 -0
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +153 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
- data/src/java/arjdbc/h2/H2Module.java +50 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +86 -0
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +74 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +76 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
- data/src/java/arjdbc/jdbc/Callable.java +44 -0
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +77 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
- data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
- data/src/java/arjdbc/jdbc/DriverWrapper.java +128 -0
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +32 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4541 -0
- data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
- data/src/java/arjdbc/jdbc/WithResultSet.java +37 -0
- data/src/java/arjdbc/mssql/MSSQLModule.java +91 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +193 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +140 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +456 -0
- data/src/java/arjdbc/oracle/OracleModule.java +81 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +477 -0
- data/src/java/arjdbc/postgresql/ByteaUtils.java +171 -0
- data/src/java/arjdbc/postgresql/DriverImplementation.java +78 -0
- data/src/java/arjdbc/postgresql/PGDriverImplementation.java +535 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +189 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +489 -0
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +93 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +405 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/DateTimeUtils.java +517 -0
- data/src/java/arjdbc/util/NumberUtils.java +50 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +139 -0
- data/src/java/arjdbc/util/StringCache.java +60 -0
- data/src/java/arjdbc/util/StringHelper.java +155 -0
- metadata +288 -0
@@ -0,0 +1,517 @@
|
|
1
|
+
/*
|
2
|
+
* The MIT License
|
3
|
+
*
|
4
|
+
* Copyright 2014 Karol Bucek.
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
11
|
+
* furnished to do so, subject to the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be included in
|
14
|
+
* all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
* THE SOFTWARE.
|
23
|
+
*/
|
24
|
+
package arjdbc.util;
|
25
|
+
|
26
|
+
import java.sql.Date;
|
27
|
+
import java.sql.Time;
|
28
|
+
import java.sql.Timestamp;
|
29
|
+
import java.util.TimeZone;
|
30
|
+
|
31
|
+
import org.joda.time.DateTime;
|
32
|
+
import org.joda.time.DateTimeZone;
|
33
|
+
import org.jruby.Ruby;
|
34
|
+
import org.jruby.RubyClass;
|
35
|
+
import org.jruby.RubyFixnum;
|
36
|
+
import org.jruby.RubyFloat;
|
37
|
+
import org.jruby.RubyString;
|
38
|
+
import org.jruby.RubyTime;
|
39
|
+
import org.jruby.runtime.ThreadContext;
|
40
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
41
|
+
import org.jruby.util.ByteList;
|
42
|
+
|
43
|
+
import static arjdbc.jdbc.RubyJdbcConnection.getBase;
|
44
|
+
import static arjdbc.util.StringHelper.decByte;
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Utilities for handling/converting dates and times.
|
48
|
+
* @author kares
|
49
|
+
*/
|
50
|
+
public abstract class DateTimeUtils {
|
51
|
+
|
52
|
+
@SuppressWarnings("deprecation")
|
53
|
+
public static ByteList timeToString(final Time time) {
|
54
|
+
final ByteList str = new ByteList(8); // hh:mm:ss
|
55
|
+
|
56
|
+
int hours = time.getHours();
|
57
|
+
int minutes = time.getMinutes();
|
58
|
+
int seconds = time.getSeconds();
|
59
|
+
|
60
|
+
str.append( decByte( hours / 10 ) );
|
61
|
+
str.append( decByte( hours % 10 ) );
|
62
|
+
|
63
|
+
str.append( ':' );
|
64
|
+
|
65
|
+
str.append( decByte( minutes / 10 ) );
|
66
|
+
str.append( decByte( minutes % 10 ) );
|
67
|
+
|
68
|
+
str.append( ':' );
|
69
|
+
|
70
|
+
str.append( decByte( seconds / 10 ) );
|
71
|
+
str.append( decByte( seconds % 10 ) );
|
72
|
+
|
73
|
+
return str;
|
74
|
+
}
|
75
|
+
|
76
|
+
@SuppressWarnings("deprecation")
|
77
|
+
public static ByteList dateToString(final Date date) {
|
78
|
+
final ByteList str = new ByteList(10); // "2000-00-00"
|
79
|
+
|
80
|
+
int year = date.getYear() + 1900;
|
81
|
+
int month = date.getMonth() + 1;
|
82
|
+
int day = date.getDate();
|
83
|
+
|
84
|
+
str.append( decByte( ( year / 1000 ) % 10 ) );
|
85
|
+
str.append( decByte( ( year / 100 ) % 10 ) );
|
86
|
+
str.append( decByte( ( year / 10 ) % 10 ) );
|
87
|
+
str.append( decByte( year % 10 ) );
|
88
|
+
|
89
|
+
str.append( '-' );
|
90
|
+
|
91
|
+
str.append( decByte( month / 10 ) );
|
92
|
+
str.append( decByte( month % 10 ) );
|
93
|
+
|
94
|
+
str.append( '-' );
|
95
|
+
|
96
|
+
str.append( decByte( day / 10 ) );
|
97
|
+
str.append( decByte( day % 10 ) );
|
98
|
+
|
99
|
+
return str;
|
100
|
+
}
|
101
|
+
|
102
|
+
@SuppressWarnings("deprecation")
|
103
|
+
public static ByteList timestampToString(final Timestamp timestamp) {
|
104
|
+
final ByteList str = new ByteList(29); // yyyy-mm-dd hh:mm:ss.fffffffff
|
105
|
+
|
106
|
+
int year = timestamp.getYear() + 1900;
|
107
|
+
int month = timestamp.getMonth() + 1;
|
108
|
+
int day = timestamp.getDate();
|
109
|
+
int hours = timestamp.getHours();
|
110
|
+
int minutes = timestamp.getMinutes();
|
111
|
+
int seconds = timestamp.getSeconds();
|
112
|
+
int nanos = timestamp.getNanos();
|
113
|
+
|
114
|
+
str.append( decByte( ( year / 1000 ) % 10 ) );
|
115
|
+
str.append( decByte( ( year / 100 ) % 10 ) );
|
116
|
+
str.append( decByte( ( year / 10 ) % 10 ) );
|
117
|
+
str.append( decByte( year % 10 ) );
|
118
|
+
|
119
|
+
str.append( '-' );
|
120
|
+
|
121
|
+
str.append( decByte( month / 10 ) );
|
122
|
+
str.append( decByte( month % 10 ) );
|
123
|
+
|
124
|
+
str.append( '-' );
|
125
|
+
|
126
|
+
str.append( decByte( day / 10 ) );
|
127
|
+
str.append( decByte( day % 10 ) );
|
128
|
+
|
129
|
+
if ( hours != 0 || minutes != 0 || seconds != 0 || nanos != 0 ) {
|
130
|
+
str.append(' ');
|
131
|
+
|
132
|
+
str.append( decByte( hours / 10 ) );
|
133
|
+
str.append( decByte( hours % 10 ) );
|
134
|
+
|
135
|
+
str.append( ':' );
|
136
|
+
|
137
|
+
str.append( decByte( minutes / 10 ) );
|
138
|
+
str.append( decByte( minutes % 10 ) );
|
139
|
+
|
140
|
+
str.append( ':' );
|
141
|
+
|
142
|
+
str.append( decByte( seconds / 10 ) );
|
143
|
+
str.append( decByte( seconds % 10 ) );
|
144
|
+
|
145
|
+
if ( nanos != 0 ) {
|
146
|
+
str.append( '.' );
|
147
|
+
|
148
|
+
int pow = 100000000; // nanos <= 999999999
|
149
|
+
for ( int i = 0; i < 8; i++ ) {
|
150
|
+
final int b = nanos / pow;
|
151
|
+
if ( b == 0 ) break; // done (no trailing zeros)
|
152
|
+
str.append( decByte( b % 10 ) );
|
153
|
+
pow = pow / 10;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
return str;
|
159
|
+
}
|
160
|
+
|
161
|
+
@SuppressWarnings("deprecation")
|
162
|
+
public static IRubyObject newTime(final ThreadContext context, final Time time) {
|
163
|
+
//if ( time == null ) return context.nil;
|
164
|
+
final int hours = time.getHours();
|
165
|
+
final int minutes = time.getMinutes();
|
166
|
+
final int seconds = time.getSeconds();
|
167
|
+
//final int offset = time.getTimezoneOffset();
|
168
|
+
|
169
|
+
final DateTime dateTime;
|
170
|
+
if ( isDefaultTimeZoneUTC(context) ) {
|
171
|
+
dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, 0, DateTimeZone.UTC);
|
172
|
+
}
|
173
|
+
else {
|
174
|
+
dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, 0);
|
175
|
+
}
|
176
|
+
return RubyTime.newTime(context.runtime, dateTime);
|
177
|
+
}
|
178
|
+
|
179
|
+
@SuppressWarnings("deprecation")
|
180
|
+
public static IRubyObject newTime(final ThreadContext context, final Timestamp timestamp) {
|
181
|
+
//if ( time == null ) return context.nil;
|
182
|
+
|
183
|
+
final int year = timestamp.getYear() + 1900;
|
184
|
+
final int month = timestamp.getMonth() + 1;
|
185
|
+
final int day = timestamp.getDate();
|
186
|
+
final int hours = timestamp.getHours();
|
187
|
+
final int minutes = timestamp.getMinutes();
|
188
|
+
final int seconds = timestamp.getSeconds();
|
189
|
+
final int nanos = timestamp.getNanos(); // max 999-999-999
|
190
|
+
|
191
|
+
final DateTime dateTime;
|
192
|
+
if ( isDefaultTimeZoneUTC(context) ) {
|
193
|
+
dateTime = new DateTime(year, month, day, hours, minutes, seconds, 0, DateTimeZone.UTC);
|
194
|
+
}
|
195
|
+
else {
|
196
|
+
dateTime = new DateTime(year, month, day, hours, minutes, seconds, 0);
|
197
|
+
}
|
198
|
+
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
199
|
+
}
|
200
|
+
|
201
|
+
@SuppressWarnings("deprecation")
|
202
|
+
public static IRubyObject newTime(final ThreadContext context, final Date date) {
|
203
|
+
//if ( time == null ) return context.nil;
|
204
|
+
|
205
|
+
final int year = date.getYear() + 1900;
|
206
|
+
final int month = date.getMonth() + 1;
|
207
|
+
final int day = date.getDate();
|
208
|
+
|
209
|
+
DateTime dateTime = new DateTime(year, month, day, 0, 0, 0, 0);
|
210
|
+
return RubyTime.newTime(context.runtime, dateTime);
|
211
|
+
}
|
212
|
+
|
213
|
+
public static Timestamp convertToTimestamp(final RubyFloat value) {
|
214
|
+
final Timestamp timestamp = new Timestamp(value.getLongValue() * 1000); // millis
|
215
|
+
|
216
|
+
// for usec we shall not use: ((long) floatValue * 1000000) % 1000
|
217
|
+
// if ( usec >= 0 ) timestamp.setNanos( timestamp.getNanos() + usec * 1000 );
|
218
|
+
// due doubles inaccurate precision it's better to parse to_s :
|
219
|
+
final ByteList strValue = ((RubyString) value.to_s()).getByteList();
|
220
|
+
final int dot1 = strValue.lastIndexOf('.') + 1, dot4 = dot1 + 3;
|
221
|
+
final int len = strValue.getRealSize() - strValue.getBegin();
|
222
|
+
if ( dot1 > 0 && dot4 < len ) { // skip .123 but handle .1234
|
223
|
+
final int end = Math.min( len - dot4, 3 );
|
224
|
+
CharSequence usecSeq = strValue.subSequence(dot4, end);
|
225
|
+
final int usec = Integer.parseInt( usecSeq.toString() );
|
226
|
+
if ( usec < 10 ) { // 0.1234 ~> 4
|
227
|
+
timestamp.setNanos( timestamp.getNanos() + usec * 100 );
|
228
|
+
}
|
229
|
+
else if ( usec < 100 ) { // 0.12345 ~> 45
|
230
|
+
timestamp.setNanos( timestamp.getNanos() + usec * 10 );
|
231
|
+
}
|
232
|
+
else { // if ( usec < 1000 ) { // 0.123456 ~> 456
|
233
|
+
timestamp.setNanos( timestamp.getNanos() + usec );
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
return timestamp;
|
238
|
+
}
|
239
|
+
|
240
|
+
public static IRubyObject getTimeInDefaultTimeZone(final ThreadContext context, IRubyObject value) {
|
241
|
+
if ( value.respondsTo("to_time") ) {
|
242
|
+
value = value.callMethod(context, "to_time");
|
243
|
+
}
|
244
|
+
final String method = isDefaultTimeZoneUTC(context) ? "getutc" : "getlocal";
|
245
|
+
if ( value.respondsTo(method) ) {
|
246
|
+
value = value.callMethod(context, method);
|
247
|
+
}
|
248
|
+
return value;
|
249
|
+
}
|
250
|
+
|
251
|
+
public static boolean isDefaultTimeZoneUTC(final ThreadContext context) {
|
252
|
+
final String defaultTimeZone = getDefaultTimeZone(context);
|
253
|
+
if ( defaultTimeZone.length() != 3 ) return false;
|
254
|
+
return "utc".equalsIgnoreCase( defaultTimeZone );
|
255
|
+
}
|
256
|
+
|
257
|
+
private static String defaultTimeZone;
|
258
|
+
|
259
|
+
public static String getDefaultTimeZone(final ThreadContext context) {
|
260
|
+
String default_timezone = defaultTimeZone;
|
261
|
+
if ( default_timezone == null ) {
|
262
|
+
final RubyClass base = getBase(context.runtime);
|
263
|
+
default_timezone = base.callMethod(context, "default_timezone").toString(); // :utc
|
264
|
+
//synchronized (DateTimeUtils.class) { defaultTimeZone = default_timezone; }
|
265
|
+
}
|
266
|
+
return default_timezone;
|
267
|
+
}
|
268
|
+
|
269
|
+
public static double adjustTimeFromDefaultZone(final IRubyObject value) {
|
270
|
+
// Time's to_f is : ( millis * 1000 + usec ) / 1_000_000.0
|
271
|
+
final double time = value.convertToFloat().getDoubleValue(); // to_f
|
272
|
+
// NOTE: MySQL assumes default TZ thus need to adjust to match :
|
273
|
+
final int offset = TimeZone.getDefault().getOffset((long) time * 1000);
|
274
|
+
// Time's to_f is : ( millis * 1000 + usec ) / 1_000_000.0
|
275
|
+
return time - ( offset / 1000.0 );
|
276
|
+
}
|
277
|
+
|
278
|
+
public static IRubyObject parseDate(final ThreadContext context, final CharSequence str)
|
279
|
+
throws IllegalArgumentException {
|
280
|
+
final int len = str.length();
|
281
|
+
|
282
|
+
int year; int month; int day;
|
283
|
+
|
284
|
+
int start = nonSpaceIndex(str, 0, len); // Skip leading whitespace
|
285
|
+
int end = nonDigitIndex(str, start, len);
|
286
|
+
|
287
|
+
if ( end >= len ) {
|
288
|
+
throw new IllegalArgumentException("unexpected date value: '" + str + "'");
|
289
|
+
}
|
290
|
+
|
291
|
+
// year
|
292
|
+
year = extractIntValue(str, start, end);
|
293
|
+
start = end + 1; // Skip '-'
|
294
|
+
|
295
|
+
// month
|
296
|
+
end = nonDigitIndex(str, start, len);
|
297
|
+
month = extractIntValue(str, start, end);
|
298
|
+
|
299
|
+
//sep = str.charAt(end);
|
300
|
+
//if ( sep != '-' ) {
|
301
|
+
// throw new NumberFormatException("expected date to be dash-separated, got '" + sep + "'");
|
302
|
+
//}
|
303
|
+
|
304
|
+
start = end + 1; // Skip '-'
|
305
|
+
|
306
|
+
// day of month
|
307
|
+
end = nonDigitIndex(str, start, len);
|
308
|
+
day = extractIntValue(str, start, end);
|
309
|
+
|
310
|
+
final Ruby runtime = context.runtime;
|
311
|
+
return runtime.getClass("Date").
|
312
|
+
callMethod(context, "new", new IRubyObject[] {
|
313
|
+
RubyFixnum.newFixnum(runtime, year),
|
314
|
+
RubyFixnum.newFixnum(runtime, month),
|
315
|
+
RubyFixnum.newFixnum(runtime, day)
|
316
|
+
});
|
317
|
+
}
|
318
|
+
|
319
|
+
public static RubyTime parseDateTime(final ThreadContext context, final CharSequence str)
|
320
|
+
throws IllegalArgumentException {
|
321
|
+
|
322
|
+
boolean hasDate = false;
|
323
|
+
int year = 2000; int month = 1; int day = 1;
|
324
|
+
boolean hasTime = false;
|
325
|
+
int minute = 0; int hour = 0; int second = 0;
|
326
|
+
int millis = 0; long nanos = 0;
|
327
|
+
|
328
|
+
DateTimeZone zone = null; boolean bcEra = false;
|
329
|
+
|
330
|
+
// We try to parse these fields in order; all are optional
|
331
|
+
// (but some combinations don't make sense, e.g. if you have
|
332
|
+
// both date and time then they must be whitespace-separated).
|
333
|
+
// At least one of date and time must be present.
|
334
|
+
|
335
|
+
// leading whitespace
|
336
|
+
// yyyy-mm-dd
|
337
|
+
// whitespace
|
338
|
+
// hh:mm:ss
|
339
|
+
// whitespace
|
340
|
+
// timezone in one of the formats: +hh, -hh, +hh:mm, -hh:mm
|
341
|
+
// whitespace
|
342
|
+
// if date is present, an era specifier: AD or BC
|
343
|
+
// trailing whitespace
|
344
|
+
|
345
|
+
final int len = str.length();
|
346
|
+
|
347
|
+
int start = nonSpaceIndex(str, 0, len); // Skip leading whitespace
|
348
|
+
int end = nonDigitIndex(str, start, len);
|
349
|
+
|
350
|
+
// Possibly read date.
|
351
|
+
if ( end < len && str.charAt(end) == '-' ) {
|
352
|
+
hasDate = true;
|
353
|
+
|
354
|
+
// year
|
355
|
+
year = extractIntValue(str, start, end);
|
356
|
+
start = end + 1; // Skip '-'
|
357
|
+
|
358
|
+
// month
|
359
|
+
end = nonDigitIndex(str, start, len);
|
360
|
+
month = extractIntValue(str, start, end);
|
361
|
+
|
362
|
+
char sep = str.charAt(end);
|
363
|
+
if ( sep != '-' ) {
|
364
|
+
throw new IllegalArgumentException("expected date to be dash-separated, got '" + sep + "'");
|
365
|
+
}
|
366
|
+
|
367
|
+
start = end + 1; // Skip '-'
|
368
|
+
|
369
|
+
// day of month
|
370
|
+
end = nonDigitIndex(str, start, len);
|
371
|
+
day = extractIntValue(str, start, end);
|
372
|
+
|
373
|
+
start = nonSpaceIndex(str, end, len); // Skip trailing whitespace
|
374
|
+
}
|
375
|
+
|
376
|
+
// Possibly read time.
|
377
|
+
if ( start < len && Character.isDigit( str.charAt(start) ) ) {
|
378
|
+
hasTime = true;
|
379
|
+
|
380
|
+
// hours
|
381
|
+
end = nonDigitIndex(str, start, len);
|
382
|
+
hour = extractIntValue(str, start, end);
|
383
|
+
|
384
|
+
//sep = str.charAt(end);
|
385
|
+
//if ( sep != ':' ) {
|
386
|
+
// throw new IllegalArgumentException("expected time to be colon-separated, got '" + sep + "'");
|
387
|
+
//}
|
388
|
+
|
389
|
+
start = end + 1; // Skip ':'
|
390
|
+
|
391
|
+
// minutes
|
392
|
+
end = nonDigitIndex(str, start, len);
|
393
|
+
minute = extractIntValue(str, start, end);
|
394
|
+
|
395
|
+
//sep = str.charAt(end);
|
396
|
+
//if ( sep != ':' ) {
|
397
|
+
// throw new IllegalArgumentException("expected time to be colon-separated, got '" + sep + "'");
|
398
|
+
//}
|
399
|
+
|
400
|
+
start = end + 1; // Skip ':'
|
401
|
+
|
402
|
+
// seconds
|
403
|
+
end = nonDigitIndex(str, start, len);
|
404
|
+
second = extractIntValue(str, start, end);
|
405
|
+
start = end;
|
406
|
+
|
407
|
+
// Fractional seconds.
|
408
|
+
if ( start < len && str.charAt(start) == '.' ) {
|
409
|
+
end = nonDigitIndex(str, start + 1, len); // Skip '.'
|
410
|
+
int numlen = end - (start + 1);
|
411
|
+
if (numlen <= 3) {
|
412
|
+
millis = extractIntValue(str, start + 1, end);
|
413
|
+
for ( ; numlen < 3; ++numlen ) millis *= 10;
|
414
|
+
}
|
415
|
+
else {
|
416
|
+
nanos = extractIntValue(str, start + 1, end);
|
417
|
+
for ( ; numlen < 9; ++numlen ) nanos *= 10;
|
418
|
+
}
|
419
|
+
|
420
|
+
start = end;
|
421
|
+
}
|
422
|
+
|
423
|
+
start = nonSpaceIndex(str, start, len); // Skip trailing whitespace
|
424
|
+
}
|
425
|
+
|
426
|
+
// Possibly read timezone.
|
427
|
+
char sep = start < len ? str.charAt(start) : '\0';
|
428
|
+
if ( sep == '+' || sep == '-' ) {
|
429
|
+
int zoneSign = (sep == '-') ? -1 : 1;
|
430
|
+
int hoursOffset, minutesOffset, secondsOffset;
|
431
|
+
|
432
|
+
end = nonDigitIndex(str, start + 1, len); // Skip +/-
|
433
|
+
hoursOffset = extractIntValue(str, start + 1, end);
|
434
|
+
start = end;
|
435
|
+
|
436
|
+
if ( start < len && str.charAt(start) == ':' ) {
|
437
|
+
end = nonDigitIndex(str, start + 1, len); // Skip ':'
|
438
|
+
minutesOffset = extractIntValue(str, start + 1, end);
|
439
|
+
start = end;
|
440
|
+
} else {
|
441
|
+
minutesOffset = 0;
|
442
|
+
}
|
443
|
+
|
444
|
+
secondsOffset = 0;
|
445
|
+
if ( start < len && str.charAt(start) == ':' ) {
|
446
|
+
end = nonDigitIndex(str, start + 1, len); // Skip ':'
|
447
|
+
secondsOffset = extractIntValue(str, start + 1, end);
|
448
|
+
start = end;
|
449
|
+
}
|
450
|
+
|
451
|
+
// Setting offset does not seem to work correctly in all
|
452
|
+
// cases.. So get a fresh calendar for a synthetic timezone
|
453
|
+
// instead
|
454
|
+
|
455
|
+
int offset = zoneSign * hoursOffset * 60;
|
456
|
+
if (offset < 0) {
|
457
|
+
offset = offset - Math.abs(minutesOffset);
|
458
|
+
} else {
|
459
|
+
offset = offset + minutesOffset;
|
460
|
+
}
|
461
|
+
offset = (offset * 60 + secondsOffset) * 1000;
|
462
|
+
zone = DateTimeZone.forOffsetMillis(offset);
|
463
|
+
|
464
|
+
start = nonSpaceIndex(str, start, len); // Skip trailing whitespace
|
465
|
+
}
|
466
|
+
|
467
|
+
if ( hasDate && start < len ) {
|
468
|
+
final char e1 = str.charAt(start);
|
469
|
+
if ( e1 == 'A' && str.charAt(start + 1) == 'D' ) {
|
470
|
+
bcEra = false; start += 2;
|
471
|
+
}
|
472
|
+
else if ( e1 == 'B' && str.charAt(start + 1) == 'C' ) {
|
473
|
+
bcEra = true; start += 2;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
|
477
|
+
if ( start < len ) {
|
478
|
+
throw new IllegalArgumentException("trailing junk: '" + str.subSequence(start, len - start) + "' on '" + str + "'");
|
479
|
+
}
|
480
|
+
if ( ! hasTime && ! hasDate ) {
|
481
|
+
throw new IllegalArgumentException("'"+ str +"' has neither date nor time");
|
482
|
+
}
|
483
|
+
|
484
|
+
if ( bcEra ) year = -1 * year;
|
485
|
+
|
486
|
+
if ( zone == null ) {
|
487
|
+
zone = isDefaultTimeZoneUTC(context) ? DateTimeZone.UTC : DateTimeZone.getDefault();
|
488
|
+
}
|
489
|
+
|
490
|
+
DateTime dateTime = new DateTime(year, month, day, hour, minute, second, millis, zone);
|
491
|
+
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
492
|
+
}
|
493
|
+
|
494
|
+
@SuppressWarnings("deprecation")
|
495
|
+
private static int nonSpaceIndex(final CharSequence str, int beg, int len) {
|
496
|
+
for ( int i = beg; i < len; i++ ) {
|
497
|
+
if ( ! Character.isSpace( str.charAt(i) ) ) return i;
|
498
|
+
}
|
499
|
+
return len;
|
500
|
+
}
|
501
|
+
|
502
|
+
private static int nonDigitIndex(final CharSequence str, int beg, int len) {
|
503
|
+
for ( int i = beg; i < len; i++ ) {
|
504
|
+
if ( ! Character.isDigit( str.charAt(i) ) ) return i;
|
505
|
+
}
|
506
|
+
return len;
|
507
|
+
}
|
508
|
+
|
509
|
+
private static int extractIntValue(final CharSequence str, int beg, int end) {
|
510
|
+
int n = 0;
|
511
|
+
for ( int i = beg; i < end; i++ ) {
|
512
|
+
n = 10 * n + ( str.charAt(i) - '0' );
|
513
|
+
}
|
514
|
+
return n;
|
515
|
+
}
|
516
|
+
|
517
|
+
}
|