knjrbfw 0.0.32 → 0.0.33
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 +2 -0
- data/Gemfile.lock +38 -0
- data/VERSION +1 -1
- data/knjrbfw.gemspec +11 -4
- data/lib/knj/autoload/wref.rb +6 -0
- data/lib/knj/autoload.rb +5 -3
- data/lib/knj/datarow.rb +74 -37
- data/lib/knj/errors.rb +5 -2
- data/lib/knj/http2.rb +8 -2
- data/lib/knj/knj.rb +0 -2
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql.rb +22 -4
- data/lib/knj/knjdb/drivers/mysql/knjdb_mysql_tables.rb +6 -8
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3.rb +1 -1
- data/lib/knj/knjdb/drivers/sqlite3/knjdb_sqlite3_tables.rb +6 -8
- data/lib/knj/knjdb/libknjdb.rb +27 -20
- data/lib/knj/knjdb/revision.rb +1 -1
- data/lib/knj/objects.rb +194 -109
- data/lib/knj/threadhandler.rb +2 -1
- data/lib/knj/unix_proc.rb +3 -3
- data/spec/datet_spec.rb +43 -0
- data/spec/knjrbfw_spec.rb +0 -290
- data/spec/objects_spec.rb +274 -0
- data/spec/php_spec.rb +28 -7
- data/spec/process_spec.rb +7 -1
- data/spec/web_spec.rb +61 -0
- metadata +40 -17
- data/lib/knj/wref.rb +0 -251
- data/spec/wref_spec.rb +0 -10
data/lib/knj/objects.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Knj::Objects
|
2
|
-
attr_reader :args, :events, :data
|
2
|
+
attr_reader :args, :events, :data, :ids_cache, :ids_cache_should
|
3
3
|
|
4
4
|
def initialize(args)
|
5
5
|
require "monitor"
|
@@ -8,7 +8,7 @@ class Knj::Objects
|
|
8
8
|
require "#{$knjpath}hash_methods"
|
9
9
|
|
10
10
|
@callbacks = {}
|
11
|
-
@args =
|
11
|
+
@args = args
|
12
12
|
@args[:col_id] = :id if !@args[:col_id]
|
13
13
|
@args[:class_pre] = "class_" if !@args[:class_pre]
|
14
14
|
@args[:module] = Kernel if !@args[:module]
|
@@ -18,25 +18,14 @@ class Knj::Objects
|
|
18
18
|
@data = {}
|
19
19
|
@lock_require = Monitor.new
|
20
20
|
|
21
|
-
require "
|
21
|
+
require "wref" if @args[:cache] == :weak
|
22
22
|
|
23
|
+
#Set up various events.
|
23
24
|
@events = Knj::Event_handler.new
|
24
|
-
@events.add_event(
|
25
|
-
|
26
|
-
|
27
|
-
)
|
28
|
-
@events.add_event(
|
29
|
-
:name => :no_date,
|
30
|
-
:connections_max => 1
|
31
|
-
)
|
32
|
-
@events.add_event(
|
33
|
-
:name => :missing_class,
|
34
|
-
:connections_max => 1
|
35
|
-
)
|
36
|
-
@events.add_event(
|
37
|
-
:name => :require_class,
|
38
|
-
:connections_max => 1
|
39
|
-
)
|
25
|
+
@events.add_event(:name => :no_html, :connections_max => 1)
|
26
|
+
@events.add_event(:name => :no_date, :connections_max => 1)
|
27
|
+
@events.add_event(:name => :missing_class, :connections_max => 1)
|
28
|
+
@events.add_event(:name => :require_class, :connections_max => 1)
|
40
29
|
|
41
30
|
raise "No DB given." if !@args[:db] and !@args[:custom]
|
42
31
|
raise "No class path given." if !@args[:class_path] and (@args[:require] or !@args.key?(:require))
|
@@ -60,6 +49,31 @@ class Knj::Objects
|
|
60
49
|
self.load_class(load_class)
|
61
50
|
end
|
62
51
|
end
|
52
|
+
|
53
|
+
#Set up ID-caching.
|
54
|
+
@ids_cache_should = {}
|
55
|
+
|
56
|
+
if @args[:models]
|
57
|
+
@ids_cache = {}
|
58
|
+
|
59
|
+
@args[:models].each do |classname, classargs|
|
60
|
+
@ids_cache_should[classname] = true if classargs[:cache_ids]
|
61
|
+
self.cache_ids(classname)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#Caches all IDs for a specific classname.
|
67
|
+
def cache_ids(classname)
|
68
|
+
classname = classname.to_sym
|
69
|
+
return nil if !@ids_cache_should or !@ids_cache_should[classname]
|
70
|
+
|
71
|
+
newcache = {}
|
72
|
+
@args[:db].q("SELECT `#{@args[:col_id]}` FROM `#{classname}` ORDER BY `#{@args[:col_id]}`") do |data|
|
73
|
+
newcache[data[@args[:col_id]].to_i] = true
|
74
|
+
end
|
75
|
+
|
76
|
+
@ids_cache[classname] = newcache
|
63
77
|
end
|
64
78
|
|
65
79
|
def init_class(classname)
|
@@ -67,7 +81,7 @@ class Knj::Objects
|
|
67
81
|
return false if @objects.key?(classname)
|
68
82
|
|
69
83
|
if @args[:cache] == :weak
|
70
|
-
@objects[classname] =
|
84
|
+
@objects[classname] = Wref_map.new
|
71
85
|
else
|
72
86
|
@objects[classname] = {}
|
73
87
|
end
|
@@ -116,6 +130,21 @@ class Knj::Objects
|
|
116
130
|
@callbacks[args["object"]][conn_id] = args
|
117
131
|
end
|
118
132
|
|
133
|
+
#Returns true if the given signal is connected to the given object.
|
134
|
+
def connected?(args)
|
135
|
+
raise "No object given." if !args["object"]
|
136
|
+
raise "No signal given." if !args.key?("signal")
|
137
|
+
|
138
|
+
if @callbacks.key?(args["object"])
|
139
|
+
@callbacks[args["object"]].clone.each do |ckey, callback|
|
140
|
+
return true if callback.key?("signal") and callback["signal"] == args["signal"]
|
141
|
+
return true if callback.key?("signals") and callback["signals"].index(args["signal"]) != nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
|
119
148
|
#This method is used to call the connected callbacks for an event.
|
120
149
|
def call(args, &block)
|
121
150
|
classstr = args["object"].class.to_s.split("::").last
|
@@ -222,8 +251,57 @@ class Knj::Objects
|
|
222
251
|
classob.datarow_init(pass_arg) if classob.respond_to?(:datarow_init)
|
223
252
|
end
|
224
253
|
|
254
|
+
#Returns the instance of classname, but only if it already exists.
|
255
|
+
def get_if_cached(classname, id)
|
256
|
+
classname = classname.to_sym
|
257
|
+
id = id.to_i
|
258
|
+
|
259
|
+
if wref_map = @objects[classname] and obj = wref_map.get!(id)
|
260
|
+
return obj
|
261
|
+
end
|
262
|
+
|
263
|
+
return nil
|
264
|
+
end
|
265
|
+
|
266
|
+
#Returns true if a row of the given classname and the ID exists. Will use ID-cache if set in arguments and spawned otherwise it will do an actual lookup.
|
267
|
+
#===Examples
|
268
|
+
# print "User 5 exists." if ob.exists?(:User, 5)
|
269
|
+
def exists?(classname, id)
|
270
|
+
#Make sure the given data are in the correct types.
|
271
|
+
classname = classname.to_sym
|
272
|
+
id = id.to_i
|
273
|
+
|
274
|
+
#Check if ID-cache is enabled for that classname. Avoid SQL-lookup by using that.
|
275
|
+
if @ids_cache_should.key?(classname)
|
276
|
+
if @ids_cache[classname].key?(id)
|
277
|
+
return true
|
278
|
+
else
|
279
|
+
return false
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
#If the object currently exists in cache, we dont have to do a lookup either.
|
284
|
+
return true if @objects.key?(classname) and obj = @objects[classname].get!(id) and !obj.deleted?
|
285
|
+
|
286
|
+
#Okay - no other options than to actually do a real lookup.
|
287
|
+
begin
|
288
|
+
table = @args[:module].const_get(classname).table
|
289
|
+
row = @args[:db].single(table, {@args[:col_id] => id})
|
290
|
+
|
291
|
+
if row
|
292
|
+
return true
|
293
|
+
else
|
294
|
+
return false
|
295
|
+
end
|
296
|
+
rescue Knj::Errors::NotFound
|
297
|
+
return false
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
225
301
|
#Gets an object from the ID or the full data-hash in the database.
|
226
|
-
|
302
|
+
#===Examples
|
303
|
+
# inst = ob.get(:User, 5)
|
304
|
+
def get(classname, data, args = nil)
|
227
305
|
classname = classname.to_sym
|
228
306
|
|
229
307
|
if data.is_a?(Integer) or data.is_a?(String) or data.is_a?(Fixnum)
|
@@ -257,11 +335,11 @@ class Knj::Objects
|
|
257
335
|
|
258
336
|
#Spawn object.
|
259
337
|
if @args[:datarow] or @args[:custom]
|
260
|
-
obj = @args[:module].const_get(classname).new(
|
338
|
+
obj = @args[:module].const_get(classname).new(data, args)
|
261
339
|
else
|
262
|
-
|
263
|
-
|
264
|
-
obj = @args[:module].const_get(classname).new(*
|
340
|
+
pass_args = [data]
|
341
|
+
pass_args = pass_args | @args[:extra_args] if @args[:extra_args]
|
342
|
+
obj = @args[:module].const_get(classname).new(*pass_args)
|
265
343
|
end
|
266
344
|
|
267
345
|
#Save object in cache.
|
@@ -489,36 +567,44 @@ class Knj::Objects
|
|
489
567
|
end
|
490
568
|
|
491
569
|
#Add a new object to the database and to the cache.
|
492
|
-
|
570
|
+
#===Examples
|
571
|
+
# obj = ob.add(:User, {:username => "User 1"})
|
572
|
+
def add(classname, data = {}, args = nil)
|
493
573
|
raise "data-variable was not a hash: '#{data.class.name}'." if !data.is_a?(Hash)
|
494
574
|
classname = classname.to_sym
|
495
575
|
self.requireclass(classname)
|
496
576
|
|
497
577
|
if @args[:datarow]
|
498
578
|
classobj = @args[:module].const_get(classname)
|
499
|
-
if classobj.respond_to?(:add)
|
500
|
-
classobj.add(Knj::Hash_methods.new(
|
501
|
-
:ob => self,
|
502
|
-
:db => self.db,
|
503
|
-
:data => data
|
504
|
-
))
|
505
|
-
end
|
506
579
|
|
580
|
+
#Run the class 'add'-method to check various data.
|
581
|
+
classobj.add(Knj::Hash_methods.new(:ob => self, :db => @args[:db], :data => data)) if classobj.respond_to?(:add)
|
582
|
+
|
583
|
+
#Check if various required data is given. If not then raise an error telling about it.
|
507
584
|
required_data = classobj.required_data
|
508
585
|
required_data.each do |req_data|
|
509
|
-
if !data.key?(req_data[:col])
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
586
|
+
raise "No '#{req_data[:class]}' given by the data '#{req_data[:col]}'." if !data.key?(req_data[:col])
|
587
|
+
raise "The '#{req_data[:class]}' by ID '#{data[req_data[:col]]}' could not be found with the data '#{req_data[:col]}'." if !self.exists?(req_data[:class], data[req_data[:col]])
|
588
|
+
end
|
589
|
+
|
590
|
+
#If 'skip_ret' is given, then the ID wont be looked up and the object wont be spawned. Be aware the connected events wont be executed either. In return it will go a lot faster.
|
591
|
+
if args and args[:skip_ret] and !@ids_cache_should.key?(classname)
|
592
|
+
ins_args = nil
|
593
|
+
else
|
594
|
+
ins_args = {:return_id => true}
|
518
595
|
end
|
519
596
|
|
520
|
-
|
521
|
-
|
597
|
+
#Insert and (maybe?) get ID.
|
598
|
+
ins_id = @args[:db].insert(classobj.table, data, ins_args).to_i
|
599
|
+
|
600
|
+
#Add ID to ID-cache if ID-cache is active for that classname.
|
601
|
+
@ids_cache[classname][ins_id] = true if ins_id != 0 and @ids_cache_should.key?(classname)
|
602
|
+
|
603
|
+
#Skip the rest if we are told not to return result.
|
604
|
+
return nil if args and args[:skip_ret]
|
605
|
+
|
606
|
+
#Spawn the object.
|
607
|
+
retob = self.get(classname, ins_id, {:skip_reload => true})
|
522
608
|
elsif @args[:custom]
|
523
609
|
classobj = @args[:module].const_get(classname)
|
524
610
|
retob = classobj.add(Knj::Hash_methods.new(
|
@@ -532,14 +618,14 @@ class Knj::Objects
|
|
532
618
|
end
|
533
619
|
|
534
620
|
self.call("object" => retob, "signal" => "add")
|
535
|
-
if retob.respond_to?(:add_after)
|
536
|
-
retob.send(:add_after, {})
|
537
|
-
end
|
621
|
+
retob.send(:add_after, {}) if retob.respond_to?(:add_after)
|
538
622
|
|
539
623
|
return retob
|
540
624
|
end
|
541
625
|
|
542
626
|
#Adds several objects to the database at once. This is faster than adding every single object by itself, since this will do multi-inserts if supported by the database.
|
627
|
+
#===Examples
|
628
|
+
# ob.adds(:User, [{:username => "User 1"}, {:username => "User 2"})
|
543
629
|
def adds(classname, datas)
|
544
630
|
if !@args[:datarow]
|
545
631
|
datas.each do |data|
|
@@ -559,6 +645,8 @@ class Knj::Objects
|
|
559
645
|
|
560
646
|
db.insert_multi(classname, datas)
|
561
647
|
end
|
648
|
+
|
649
|
+
self.cache_ids(classname)
|
562
650
|
end
|
563
651
|
|
564
652
|
#Calls a static method on a class. Passes the d-variable which contains the Objects-object, database-reference and more...
|
@@ -623,9 +711,13 @@ class Knj::Objects
|
|
623
711
|
end
|
624
712
|
|
625
713
|
#Delete an object. Both from the database and from the cache.
|
714
|
+
#===Examples
|
715
|
+
# user = ob.get(:User, 1)
|
716
|
+
# ob.delete(user)
|
626
717
|
def delete(object)
|
627
718
|
#Return false if the object has already been deleted.
|
628
719
|
return false if object.deleted?
|
720
|
+
classname = object.class.classname.to_sym
|
629
721
|
|
630
722
|
self.call("object" => object, "signal" => "delete_before")
|
631
723
|
self.unset(object)
|
@@ -656,6 +748,7 @@ class Knj::Objects
|
|
656
748
|
@args[:db].delete(object.table, {:id => obj_id})
|
657
749
|
end
|
658
750
|
|
751
|
+
@ids_cache[classname].delete(obj_id.to_i) if @ids_cache_should.key?(classname)
|
659
752
|
self.call("object" => object, "signal" => "delete")
|
660
753
|
object.destroy
|
661
754
|
end
|
@@ -667,87 +760,79 @@ class Knj::Objects
|
|
667
760
|
self.delete(obj)
|
668
761
|
end
|
669
762
|
else
|
670
|
-
|
671
|
-
ids = []
|
672
|
-
objs.each do |obj|
|
673
|
-
next if obj.deleted?
|
674
|
-
ids << obj.id
|
675
|
-
if ids.length >= 1000
|
676
|
-
arr_ids << ids
|
677
|
-
ids = []
|
678
|
-
end
|
679
|
-
|
680
|
-
obj.delete if obj.respond_to?(:delete)
|
681
|
-
end
|
763
|
+
tables = {}
|
682
764
|
|
683
|
-
|
684
|
-
|
685
|
-
|
765
|
+
begin
|
766
|
+
objs.each do |obj|
|
767
|
+
next if obj.deleted?
|
768
|
+
tablen = obj.table
|
769
|
+
|
770
|
+
if !tables.key?(tablen)
|
771
|
+
tables[tablen] = []
|
772
|
+
end
|
773
|
+
|
774
|
+
tables[tablen] << obj.id
|
775
|
+
obj.delete if obj.respond_to?(:delete)
|
776
|
+
|
777
|
+
#Remove from ID-cache.
|
778
|
+
classname = obj.class.classname.to_sym
|
779
|
+
@ids_cache[classname].delete(obj.id.to_i) if @ids_cache_should.key?(classname)
|
780
|
+
|
781
|
+
#Unset any data on the object, so it seems deleted.
|
782
|
+
obj.destroy
|
783
|
+
end
|
784
|
+
ensure
|
785
|
+
#An exception may occur, and we should make sure, that objects that has gotten 'delete' called also are deleted from their tables.
|
786
|
+
tables.each do |table, ids|
|
787
|
+
ids.each_slice(1000) do |ids_slice|
|
788
|
+
@args[:db].delete(table, {:id => ids_slice})
|
789
|
+
end
|
790
|
+
end
|
686
791
|
end
|
687
792
|
end
|
688
793
|
end
|
689
794
|
|
690
|
-
#
|
795
|
+
#Try to clean up objects by unsetting everything, start the garbagecollector, get all the remaining objects via ObjectSpace and set them again. Some (if not all) should be cleaned up and our cache should still be safe... dirty but works.
|
691
796
|
def clean(classn)
|
692
|
-
return false if @args[:cache] == :weak or @args[:cache] == :none
|
693
|
-
|
694
797
|
if classn.is_a?(Array)
|
695
798
|
classn.each do |realclassn|
|
696
799
|
self.clean(realclassn)
|
697
800
|
end
|
801
|
+
|
802
|
+
return nil
|
803
|
+
end
|
804
|
+
|
805
|
+
if @args[:cache] == :weak
|
806
|
+
@objects[classn].clean
|
807
|
+
elsif @args[:cache] == :none
|
808
|
+
return false
|
698
809
|
else
|
699
810
|
return false if !@objects.key?(classn)
|
700
811
|
@objects[classn] = {}
|
701
812
|
GC.start
|
813
|
+
|
814
|
+
@objects.keys.each do |classn|
|
815
|
+
data = @objects[classn]
|
816
|
+
classobj = @args[:module].const_get(classn)
|
817
|
+
ObjectSpace.each_object(classobj) do |obj|
|
818
|
+
begin
|
819
|
+
data[obj.id.to_i] = obj
|
820
|
+
rescue => e
|
821
|
+
if e.message == "No data on object."
|
822
|
+
#Object has been unset - skip it.
|
823
|
+
next
|
824
|
+
end
|
825
|
+
|
826
|
+
raise e
|
827
|
+
end
|
828
|
+
end
|
829
|
+
end
|
702
830
|
end
|
703
831
|
end
|
704
832
|
|
705
833
|
#Erases the whole cache and regenerates is from ObjectSpace if not running weak-link-caching. If running weaklink-caching then only removes the dead links.
|
706
834
|
def clean_all
|
707
|
-
|
708
|
-
return false if @args[:cache] == :none
|
709
|
-
|
710
|
-
classnames = []
|
711
|
-
@objects.keys.each do |classn|
|
712
|
-
classnames << classn
|
713
|
-
end
|
714
|
-
|
715
|
-
classnames.each do |classn|
|
716
|
-
@objects[classn] = {}
|
717
|
-
end
|
718
|
-
|
719
|
-
GC.start
|
720
|
-
self.clean_recover
|
721
|
-
end
|
722
|
-
|
723
|
-
#Runs through all objects-weaklink-references and removes the weaklinks if the object has been recycled.
|
724
|
-
def clean_all_weak
|
725
|
-
@objects.keys.each do |classn|
|
726
|
-
@objects[classn].clean
|
727
|
-
end
|
728
|
-
end
|
729
|
-
|
730
|
-
#Regenerates cache from ObjectSpace. Its pretty dangerous but can be used in envs where WeakRef is not supported (did someone say Rhodes?).
|
731
|
-
def clean_recover
|
732
|
-
return false if @args[:cache] == :weak or @args[:cache] == :none
|
733
|
-
return false if RUBY_ENGINE == "jruby" and !JRuby.objectspace
|
734
|
-
|
735
|
-
@objects.keys.each do |classn|
|
736
|
-
data = @objects[classn]
|
737
|
-
classobj = @args[:module].const_get(classn)
|
738
|
-
ObjectSpace.each_object(classobj) do |obj|
|
739
|
-
begin
|
740
|
-
data[obj.id.to_i] = obj
|
741
|
-
rescue => e
|
742
|
-
if e.message == "No data on object."
|
743
|
-
#Object has been unset - skip it.
|
744
|
-
next
|
745
|
-
end
|
746
|
-
|
747
|
-
raise e
|
748
|
-
end
|
749
|
-
end
|
750
|
-
end
|
835
|
+
self.clean(@objects.keys)
|
751
836
|
end
|
752
837
|
end
|
753
838
|
|
data/lib/knj/threadhandler.rb
CHANGED
@@ -3,6 +3,7 @@ class Knj::Threadhandler
|
|
3
3
|
|
4
4
|
def initialize(args = {})
|
5
5
|
require "#{$knjpath}errors"
|
6
|
+
require "tsafe"
|
6
7
|
|
7
8
|
@args = args
|
8
9
|
@objects = []
|
@@ -114,7 +115,7 @@ class Knj::Threadhandler
|
|
114
115
|
else
|
115
116
|
#No free objects, but we can spawn a new one and use that...
|
116
117
|
newobj = @spawn_new_block.call
|
117
|
-
@objects <<
|
118
|
+
@objects << Tsafe::MonHash.new.merge(
|
118
119
|
:free => false,
|
119
120
|
:object => newobj
|
120
121
|
)
|
data/lib/knj/unix_proc.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "
|
1
|
+
require "wref"
|
2
2
|
|
3
3
|
#This class handels various stuff regarding Unix-processes.
|
4
4
|
class Knj::Unix_proc
|
5
5
|
attr_reader :data
|
6
6
|
|
7
|
-
PROCS =
|
7
|
+
PROCS = Wref_map.new
|
8
8
|
MUTEX = Mutex.new
|
9
9
|
|
10
10
|
def self.spawn(data)
|
@@ -13,7 +13,7 @@ class Knj::Unix_proc
|
|
13
13
|
begin
|
14
14
|
proc_ele = PROCS[pid]
|
15
15
|
proc_ele.update_data(data)
|
16
|
-
rescue
|
16
|
+
rescue Wref::Recycled
|
17
17
|
proc_ele = Knj::Unix_proc.new(data)
|
18
18
|
PROCS[pid] = proc_ele
|
19
19
|
end
|
data/spec/datet_spec.rb
CHANGED
@@ -27,4 +27,47 @@ describe "Datet" do
|
|
27
27
|
res = datet.ago_str
|
28
28
|
raise "Expected '2 days ago' but got: '#{res}'." if res != "2 days ago"
|
29
29
|
end
|
30
|
+
|
31
|
+
#From "knjrbfw_spec.rb".
|
32
|
+
it "should be able to parse various date formats." do
|
33
|
+
date = Knj::Datet.in("2011-07-09 00:00:00 UTC")
|
34
|
+
date = Knj::Datet.in("1985-06-17 01:00:00")
|
35
|
+
date = Knj::Datet.in("1985-06-17")
|
36
|
+
date = Knj::Datet.in("17/06 1985")
|
37
|
+
|
38
|
+
raise "Couldnt register type 1 nullstamp." if !Knj::Datet.is_nullstamp?("0000-00-00")
|
39
|
+
raise "Couldnt register type 2 nullstamp." if !Knj::Datet.is_nullstamp?("0000-00-00 00:00:00")
|
40
|
+
raise "Registered nullstamp on valid date." if Knj::Datet.is_nullstamp?("1985-06-17")
|
41
|
+
raise "Registered nullstamp on valid date." if Knj::Datet.is_nullstamp?("1985-06-17 10:30:00")
|
42
|
+
|
43
|
+
date = Knj::Datet.in("2011-07-09 13:05:04 +0200")
|
44
|
+
ltime = date.localtime_str
|
45
|
+
|
46
|
+
#if RUBY_VERSION.slice(0, 3) == "1.9"
|
47
|
+
# if ltime != date.time.localtime
|
48
|
+
# raise "Calculated localtime (#{ltime}) was not the same as the real Time-localtime (#{date.time.localtime})."
|
49
|
+
# end
|
50
|
+
#end
|
51
|
+
|
52
|
+
if ltime != "2011-07-09 13:05:04 +0200"
|
53
|
+
raise "Datet didnt return expected result: '#{ltime}'."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should be able to compare dates" do
|
58
|
+
date1 = Knj::Datet.in("17/06 1985")
|
59
|
+
date2 = Knj::Datet.in("18/06 1985")
|
60
|
+
date3 = Knj::Datet.in("17/06 1985")
|
61
|
+
|
62
|
+
raise "Date1 was wrongly higher than date2." if date1 > date2
|
63
|
+
|
64
|
+
if date2 > date1
|
65
|
+
#do nothing.
|
66
|
+
else
|
67
|
+
raise "Date2 was wrongly not higher than date1."
|
68
|
+
end
|
69
|
+
|
70
|
+
raise "Date1 was wrongly not the same as date3." if date1 != date3
|
71
|
+
raise "Date1 was the same as date2?" if date1 == date2
|
72
|
+
end
|
30
73
|
end
|