Skip to content

Commit

Permalink
Make Date._strptime loaded as a native ext and make map to hash conve…
Browse files Browse the repository at this point in the history
…rsion

in Java vs Ruby.  Improvement (BEFORE):

```text
system ~/work/jruby master 1423% jruby ../snippets/date_bench.rb 
Warming up --------------------------------------
           _strptime    13.890k i/100ms
Calculating -------------------------------------
_strptime    168.652k (± 5.7%) i/s -      1.681M in  10.002137s
```

AFTER:
```text
jruby ../snippets/date_bench.rb 
Warming up --------------------------------------
           _strptime    24.108k i/100ms
Calculating -------------------------------------
_strptime    291.972k (± 6.1%) i/s -      2.917M in  10.031620s
```
enebo committed Jun 19, 2017
1 parent 83098f6 commit 4323f93
Showing 4 changed files with 102 additions and 6 deletions.
17 changes: 17 additions & 0 deletions core/src/main/java/org/jruby/ext/date/DateLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.jruby.ext.date;

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.runtime.load.Library;

import java.io.IOException;

/**
* Assumes kernel will lo
*/
public class DateLibrary implements Library {
public void load(final Ruby runtime, boolean wrap) throws IOException {
RubyClass dateClass = runtime.getClass("Date");
dateClass.defineAnnotatedMethods(RubyDate.class);
}
}
83 changes: 83 additions & 0 deletions core/src/main/java/org/jruby/ext/date/RubyDate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/****** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2006, 2007 Ola Bini <ola@ologix.com>
* Copyright (C) 2007 Nick Sieger <nicksieger@gmail.com>
* Copyright (C) 2008 Vladimir Sizikov <vsizikov@gmail.com>
* Copyright (C) 2009 Joseph LaFata <joe@quibb.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.ext.date;

import org.jruby.RubyHash;
import org.jruby.RubyString;
import org.jruby.RubySymbol;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
import org.jruby.util.RubyDateParser;
import org.jruby.util.TypeConverter;

import java.util.Map;

@JRubyModule(name = "Date")
public class RubyDate {
private static final ByteList DEFAULT_FORMAT = new ByteList(new byte[] {'%', 'F'});

public static IRubyObject _strptime(ThreadContext context, IRubyObject str) {
return _strptime(context, str, context.runtime.newString(DEFAULT_FORMAT));
}

public static IRubyObject _strptime(ThreadContext context, IRubyObject string, IRubyObject format) {
RubyString stringString = (RubyString) TypeConverter.checkStringType(context.runtime, string);
RubyString formatString = (RubyString) TypeConverter.checkStringType(context.runtime, format);

Map<String, Object> map = new RubyDateParser().parse(context, formatString, stringString);
// FIXME: Remove null as return
if (map == null) return context.nil;

RubyHash hash = RubyHash.newHash(context.runtime);

for (Map.Entry<String, Object> pair: map.entrySet()) {
// FIXME: This is using JI for object coercion so we should return ruby types in value
hash.put(RubySymbol.newSymbol(context.runtime, pair.getKey()), pair.getValue());
}

return hash;
}

@JRubyMethod(meta = true, required = 1, optional = 1)
public static IRubyObject _strptime(ThreadContext context, IRubyObject self, IRubyObject[] args) {
switch(args.length) {
case 1:
return _strptime(context, args[0]);
case 2:
return _strptime(context, args[0], args[1]);
default:
throw context.runtime.newArgumentError(args.length, 1);
}
}
}
2 changes: 2 additions & 0 deletions lib/ruby/stdlib/date.rb
Original file line number Diff line number Diff line change
@@ -1948,4 +1948,6 @@ def to_datetime
private_class_method :today
public_class_method :now

# Adds native implemented methods...
org.jruby.ext.date.DateLibrary.new.load JRuby.runtime, false
end
6 changes: 0 additions & 6 deletions lib/ruby/stdlib/date/format.rb
Original file line number Diff line number Diff line change
@@ -375,12 +375,6 @@ def self._strptime_i(str, fmt, e) # :nodoc:

private_class_method :_strptime_i

def self._strptime(str, fmt='%F')
parser = org.jruby.util.RubyDateParser.new
map = parser.parse(JRuby.runtime.current_context, fmt, str)
return map.nil? ? nil : map.to_hash.inject({}){|hash,(k,v)| hash[k.to_sym] = v; hash}
end

def self.s3e(e, y, m, d, bc=false)
unless String === m
m = m.to_s

0 comments on commit 4323f93

Please sign in to comment.