added jj_temporal source code
This commit is contained in:
parent
d551f35d2f
commit
4df573d730
@ -1 +0,0 @@
|
||||
Subproject commit 8b8f6b7b3b39f254293920f4e5f0fb1ab5c1926b
|
7
jj_temporal/README.md
Normal file
7
jj_temporal/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# jj_temporal
|
||||
Eiffel date and time classes
|
||||
|
||||
Main classes: ![](docs/main_classes.png?raw=true)
|
||||
|
||||
|
||||
|
229
jj_temporal/classes/abstract_duration.e
Normal file
229
jj_temporal/classes/abstract_duration.e
Normal file
@ -0,0 +1,229 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a duration of time such as 2 hours, or 3 years, etc.
|
||||
]"
|
||||
names: "abstract_duration, duration"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_DURATION
|
||||
|
||||
inherit
|
||||
COMPARABLE
|
||||
|
||||
feature -- Access
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string, ideally with not extra characters.
|
||||
deferred
|
||||
end
|
||||
|
||||
negative: like Current
|
||||
-- The negative value of this duration
|
||||
do
|
||||
Result := twin
|
||||
Result.negate
|
||||
ensure
|
||||
negative_result: Current > zero implies Result < zero
|
||||
positive_result: Current < zero implies Result > zero
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
deferred
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
valid_result: Result.is_one
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
deferred
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
good_result: Result.is_zero
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_zero: BOOLEAN
|
||||
-- Is this duration of 0 length?
|
||||
do
|
||||
Result := equal (Current, zero)
|
||||
ensure
|
||||
valid_result: Result implies equal (Current, zero)
|
||||
end
|
||||
|
||||
is_one: BOOLEAN
|
||||
-- Is this duration neutral for '*' and '/'?
|
||||
do
|
||||
Result := equal (Current, one)
|
||||
ensure
|
||||
valid_result: Result implies equal (Current, one)
|
||||
end
|
||||
|
||||
is_negative: BOOLEAN
|
||||
-- Is current less than the 'zero' duration?
|
||||
do
|
||||
Result := Current < zero
|
||||
ensure
|
||||
valid_result: Result implies Current < zero
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_zero
|
||||
-- Make the duration have zero length.
|
||||
deferred
|
||||
ensure
|
||||
is_zero: is_zero
|
||||
end
|
||||
|
||||
|
||||
negate
|
||||
-- Reverses the sign.
|
||||
deferred
|
||||
ensure
|
||||
positive_implication: not is_negative implies old is_negative
|
||||
negative_implication: is_negative implies not old is_negative
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other other to Current.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from Current
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
deferred
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
require
|
||||
not_zero_devisor: r /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
-- For example: is current duration at least twice as long as other?
|
||||
require
|
||||
other_exists: other /= Void
|
||||
other_not_zero: not other.is_zero
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
identity alias "+": like Current
|
||||
-- Just a clone of Current. Included for symetry.
|
||||
do
|
||||
Result := twin
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
oposite alias "-": like Current
|
||||
-- Invert the sign of other.
|
||||
do
|
||||
Result := twin
|
||||
Result.negate
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
plus alias "+" (other: like Current): like Current
|
||||
-- Sum of current and other.
|
||||
do
|
||||
Result := twin
|
||||
Result.add (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
minus alias "-" (other: like Current): like Current
|
||||
-- Difference of Current and other.
|
||||
do
|
||||
Result := twin
|
||||
Result.sub (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
product alias "*" (r: DOUBLE): like Current
|
||||
-- Product of Current and 'r'.
|
||||
-- Multiply by a factor of 'r'.
|
||||
do
|
||||
Result := twin
|
||||
Result.multiply (r)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
quotient alias "/" (r: DOUBLE): like Current
|
||||
-- Quotent of Current by 'r'.
|
||||
require
|
||||
not_zero_devisor: r /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.divide (r)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
integer_quotient alias "//" (i: INTEGER): like Current
|
||||
-- Integer division of Current by 'i'.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.div (i)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
integer_remainder alias "\\" (i: INTEGER): like Current
|
||||
-- Modulo of Current by 'i'.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.mod (i)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
end
|
||||
|
387
jj_temporal/classes/abstract_interval.e
Normal file
387
jj_temporal/classes/abstract_interval.e
Normal file
@ -0,0 +1,387 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a span of time consisting of a start-time, a
|
||||
finish-time and a duration. Positive durations only.
|
||||
]"
|
||||
names: "abstract_interval, time_span, time_interval, span"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
COMPARABLE
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
start: like time_anchor
|
||||
-- Beginning moment of the time span and anchor for class.
|
||||
do
|
||||
Result := start_imp.twin
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
finish: like time_anchor
|
||||
-- Ending moment of the time span.
|
||||
do
|
||||
Result := finish_imp.twin
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
duration: like duration_anchor
|
||||
-- Length of time span.
|
||||
do
|
||||
Result := finish.time_between (start)
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_start_finish (a_start_time, a_finish_time: like time_anchor)
|
||||
-- Set the `start' and `finish' times.
|
||||
require
|
||||
times_exists: a_start_time /= Void and a_finish_time /= Void
|
||||
valid_times: a_start_time <= a_finish_time
|
||||
do
|
||||
start_imp := a_start_time.twin
|
||||
finish_imp := a_finish_time.twin
|
||||
ensure
|
||||
start_was_set: equal (start, a_start_time)
|
||||
finish_was_set: equal (finish, a_finish_time)
|
||||
end
|
||||
|
||||
set_start_duration (a_start_time: like time_anchor; a_duration: like duration_anchor)
|
||||
-- Set the `start' time and the `duration'.
|
||||
require
|
||||
start_time_exists: a_start_time /= Void
|
||||
duration_exists: a_duration /= Void
|
||||
positive_duration: not a_duration.is_negative
|
||||
do
|
||||
start_imp := a_start_time.twin
|
||||
finish_imp := a_start_time + a_duration
|
||||
ensure
|
||||
start_was_set: equal (start, a_start_time)
|
||||
duration_was_set: equal (duration, a_duration)
|
||||
end
|
||||
|
||||
set_duration_finish (a_duration: like duration_anchor; a_finish_time: like time_anchor)
|
||||
-- Set the `duration' and `finish' time.
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
positive_duration: not a_duration.is_negative
|
||||
finish_time_exists: a_finish_time /= Void
|
||||
do
|
||||
start_imp := a_finish_time - a_duration
|
||||
finish_imp := a_finish_time.twin
|
||||
ensure
|
||||
finish_was_set: equal (finish, a_finish_time)
|
||||
duration_was_set: equal (duration, a_duration)
|
||||
end
|
||||
|
||||
move (a_duration: like duration_anchor)
|
||||
-- Change the `start' and `finish' times by moving the
|
||||
-- interval by the amount represented by `a_duration'.
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
start_imp.add_duration (a_duration)
|
||||
finish_imp.add_duration (a_duration)
|
||||
ensure
|
||||
duration_unchanged: equal (duration, old duration)
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does current interval start before other or if they start at the
|
||||
-- same time, does Current end before the other?
|
||||
do
|
||||
if (start < other.start) or else
|
||||
(start.is_equal (other.start) and then finish < other.finish) then
|
||||
Result := true
|
||||
end
|
||||
ensure then
|
||||
less_than_definition: Result implies (start < other.start or else
|
||||
(start.is_equal (other.start) and then finish < other.finish))
|
||||
end
|
||||
|
||||
meets (other: like Current): BOOLEAN
|
||||
-- x.meets(y) |-----x----->|
|
||||
-- y.is_met_by(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := equal (finish, other.start)
|
||||
ensure
|
||||
Result implies equal (finish, other.start)
|
||||
Result implies Current < other
|
||||
end
|
||||
|
||||
is_met_by (other: like Current): BOOLEAN
|
||||
-- x.meets(y) |-----x----->|
|
||||
-- y.is_met_by(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := equal (start, other.finish)
|
||||
ensure
|
||||
Result implies equal (start, other.finish)
|
||||
Result implies other < Current
|
||||
end
|
||||
|
||||
is_before (other: like Current): BOOLEAN
|
||||
-- x.is_before(y) |-----x----->|
|
||||
-- y.is_after(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := finish < other.start
|
||||
ensure
|
||||
Result implies finish.is_before (other)
|
||||
Result implies Current < other
|
||||
end
|
||||
|
||||
is_after (other: like Current): BOOLEAN
|
||||
-- x.is_before(y) |-----x----->|
|
||||
-- y.is_after(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := start > other.finish
|
||||
ensure
|
||||
Result implies start.is_after (other)
|
||||
Result implies other < Current
|
||||
end
|
||||
|
||||
includes (other: like Current): BOOLEAN
|
||||
-- x.includes(y) |-----x----->|
|
||||
-- y.is_included_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := other.start.belongs (Current) and
|
||||
other.finish.belongs (Current)
|
||||
ensure
|
||||
Result implies other.start.belongs (Current);
|
||||
Result implies other.finish.belongs (Current)
|
||||
end
|
||||
|
||||
is_included_by (other: like Current): BOOLEAN
|
||||
-- x.includes(y) |-----x----->|
|
||||
-- y.is_included_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := start.belongs (other) and finish.belongs (other)
|
||||
ensure
|
||||
Result implies start.belongs (other);
|
||||
Result implies finish.belongs (other);
|
||||
end
|
||||
|
||||
overlaps (other: like Current): BOOLEAN
|
||||
-- x.overlaps(y) |-----x----->|
|
||||
-- y.is_overlapped_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := finish.belongs (other)
|
||||
ensure
|
||||
Result implies finish.belongs (other)
|
||||
end
|
||||
|
||||
is_overlapped_by (other: like Current): BOOLEAN
|
||||
-- x.overlaps(y) |-----x----->|
|
||||
-- y.is_overlapped_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := other.finish.belongs (Current)
|
||||
ensure
|
||||
Result implies other.finish.belongs (Current)
|
||||
end
|
||||
|
||||
intersects (other: like Current): BOOLEAN
|
||||
-- Do the two intervals have a least one time point in common?
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := meets (other) or is_met_by (other) or else
|
||||
includes (other) or is_included_by (other) or else
|
||||
overlaps (other) or is_overlapped_by (other)
|
||||
ensure
|
||||
Result implies meets (other) or is_met_by (other) or else
|
||||
includes (other) or is_included_by (other) or else
|
||||
overlaps (other) or is_overlapped_by (other)
|
||||
end
|
||||
|
||||
feature -- Transformation
|
||||
|
||||
unite (other: like Current)
|
||||
-- Transform into the union between this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |------------x.union(y)----------->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
local
|
||||
temp_start: like time_anchor
|
||||
temp_finish: like finish
|
||||
do
|
||||
temp_start := start.min (other.start)
|
||||
temp_finish := finish.max (other.finish)
|
||||
set_start_finish (temp_start, temp_finish);
|
||||
ensure
|
||||
valid_result: equal (start, old start.min(other.start)) and
|
||||
equal (finish, old finish.max(other.finish))
|
||||
end
|
||||
|
||||
intersect (other: like Current)
|
||||
-- Transform into the intersection of this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |--x.intersection(y)-->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
local
|
||||
temp_start: like time_anchor
|
||||
temp_finish: like finish
|
||||
do
|
||||
temp_start := start.max (other.start)
|
||||
temp_finish := finish.min (other.finish)
|
||||
set_start_finish (temp_start, temp_finish);
|
||||
ensure
|
||||
valid_result: equal (start, old start.max(other.start)) and
|
||||
equal (finish, old finish.min(other.finish))
|
||||
end
|
||||
|
||||
split (a_time: like time_anchor): like Current
|
||||
-- Transform by splitting the interval at 'a_time'.
|
||||
-- Result is the interval after 'a_time'.
|
||||
-- |
|
||||
-- time
|
||||
-- |
|
||||
-- V
|
||||
-- |-----Current----------------->|
|
||||
-- |---Current--->|----Result---->|
|
||||
-- Only valid if time is within the interval.
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
time_in_interval: a_time.belongs (Current)
|
||||
do
|
||||
Result := twin
|
||||
set_start_finish (start, a_time)
|
||||
Result.set_start_finish (a_time, Result.finish)
|
||||
ensure
|
||||
closure: equal (old Current, Result.union (Current))
|
||||
meets_result: Current.meets (Result)
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
union (other: like Current): like Current
|
||||
-- The union between this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |------------x.union(y)----------->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
do
|
||||
Result := twin
|
||||
Result.unite (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
valid_result: equal (Result.start, start.min(other.start)) and
|
||||
equal (Result.finish, finish.max(other.finish))
|
||||
end
|
||||
|
||||
intersection (other: like Current): like Current
|
||||
-- The intersection of this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |--x.intersection(y)-->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
do
|
||||
Result := twin
|
||||
Result.intersect (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
valid_result: equal (Result.start, start.max (other.start)) and
|
||||
equal (Result.finish, finish.min(other.finish))
|
||||
end
|
||||
|
||||
time_at_percent (a_ratio: DOUBLE): like time_anchor
|
||||
-- Time based on some percentage of this interval.
|
||||
-- Example 1: if 'a_ratio' is 0.0 then result = 'start'; if
|
||||
-- 'a_ratio' is 0.5 then resulting time is 1/2 the distance
|
||||
-- from start to finish; if 'a_ratio' is 2.0 then resulting time
|
||||
-- is at twice the duration from start to finish.
|
||||
do
|
||||
Result := start + (duration * a_ratio)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
start_imp: like time_anchor
|
||||
-- Used internally to prevent changes to `start' which could otherwise
|
||||
-- be induced by calls to a _TIME.
|
||||
|
||||
finish_imp: like time_anchor
|
||||
-- Used internally to prevent changes to `finish' which could otherwise
|
||||
-- be induced by calls to a _TIME.
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: ABSTRACT_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: ABSTRACT_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
is_initialized: start_imp /= Void and finish_imp /= Void
|
||||
start_before_finish: start <= finish
|
||||
positive_duration: not duration.is_negative
|
||||
|
||||
end
|
273
jj_temporal/classes/abstract_time.e
Normal file
273
jj_temporal/classes/abstract_time.e
Normal file
@ -0,0 +1,273 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a time, such as <1 Jan 98> or <10:30 P.M.> or <the moment of creation>, etc.
|
||||
]"
|
||||
names: "abstract_time, time, date"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_TIME
|
||||
|
||||
inherit
|
||||
COMPARABLE
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string, ideally with not extra characters.
|
||||
deferred
|
||||
end
|
||||
|
||||
as_integer: INTEGER
|
||||
-- The time as represented by an INTEGER.
|
||||
require
|
||||
is_representable: is_representable_as_integer
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
set_now
|
||||
-- Set current time according to timezone.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
require
|
||||
valid_string_representation: is_valid_string_representation (a_string)
|
||||
deferred
|
||||
end
|
||||
|
||||
from_integer (a_integer: INTEGER)
|
||||
-- Change Current to the time represented by `a_integer'.
|
||||
require
|
||||
valid_integer_representation: is_valid_integer_representation (a_integer)
|
||||
deferred
|
||||
end
|
||||
|
||||
add_duration (a_duration: like duration_anchor)
|
||||
-- adds a duration to Current time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
plus alias "+" (a_duration: like duration_anchor): like Current
|
||||
-- same as add_duration except returns a new time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
Result := twin
|
||||
Result.add_duration (a_duration)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
minus alias "-" (a_duration: like duration_anchor): like Current
|
||||
-- same as adding a negative duration except returns a new time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
Result := twin
|
||||
Result.add_duration (a_duration.negative)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_before (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Is this time before the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current < a_interval.start
|
||||
ensure
|
||||
valid_result: Result implies Current < a_interval.start
|
||||
end
|
||||
|
||||
is_after (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Is this time after the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current > a_interval.finish
|
||||
ensure
|
||||
valid_result: Result implies Current > a_interval.finish
|
||||
end
|
||||
|
||||
belongs (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Does this time fall somewhere during the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current >= a_interval.start and Current <= a_interval.finish
|
||||
ensure
|
||||
valid_result: Result implies Current >= a_interval.start and Current <= a_interval.finish
|
||||
end
|
||||
|
||||
is_between (time_1, time_2: like Current): BOOLEAN
|
||||
-- Is current between the two times?
|
||||
require
|
||||
others_exist: time_1 /= Void and time_2 /= Void
|
||||
do
|
||||
if time_1 < Current and Current < time_2 then
|
||||
Result := True
|
||||
elseif time_2 < Current and Current < time_1 then
|
||||
Result := True
|
||||
end
|
||||
ensure
|
||||
valid_result: Result implies ((time_1 < Current and Current < time_2) or else
|
||||
(time_2 < Current and Current < time_1))
|
||||
end
|
||||
|
||||
is_between_inclusive (time_1, time_2: like Current): BOOLEAN
|
||||
-- Is current between the two times or equal to one of the two times?
|
||||
require
|
||||
others_exist: time_1 /= Void and time_2 /= Void
|
||||
do
|
||||
if time_1 <= Current and Current <= time_2 then
|
||||
Result := True
|
||||
elseif time_2 <= Current and Current <= time_1 then
|
||||
Result := True
|
||||
end
|
||||
ensure
|
||||
valid_result: Result implies ((time_1 <= Current and Current <= time_2) or else
|
||||
(time_2 <= Current and Current <= time_1))
|
||||
end
|
||||
|
||||
percent_of (a_interval: like interval_anchor): DOUBLE
|
||||
-- Where does this time fall in relation to the interval?
|
||||
-- If current time is before the interval then result should be negative.
|
||||
-- If current time is after the interval then result should be > 1 (i.e. > 100%).
|
||||
-- If current time belongs to the interval then result should be between 0 and 1.
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
local
|
||||
int: like Interval_anchor
|
||||
do
|
||||
-- int := twin (a_interval)
|
||||
int := a_interval.deep_twin
|
||||
if is_before (a_interval) then
|
||||
int.set_start_finish (Current, a_interval.start)
|
||||
if not a_interval.duration.is_zero then
|
||||
Result := -(int.duration.percent_of (a_interval.duration))
|
||||
end
|
||||
else
|
||||
int.set_start_finish (a_interval.start, Current)
|
||||
if not a_interval.duration.is_zero then
|
||||
Result := int.duration.percent_of (a_interval.duration)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
negative_if_before: Result < 0 implies Current.is_before (a_interval)
|
||||
zero_to_one_if_belongs: (Result >= 0 and Result <= 1) implies Current.belongs (a_interval)
|
||||
over_one_if_after: Result > 1 implies Current.is_after (a_interval)
|
||||
end
|
||||
|
||||
time_between (other: like Current): like duration_anchor
|
||||
-- The duration of time between Current and other
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
deferred
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in the range reconizable by Current?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
C_date: C_DATE
|
||||
-- Used to set the date and time based on system clock.
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Test used by invariant.
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: ABSTRACT_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: ABSTRACT_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
always_valid: is_valid
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2015, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
|
||||
|
||||
|
255
jj_temporal/classes/c_date.e
Normal file
255
jj_temporal/classes/c_date.e
Normal file
@ -0,0 +1,255 @@
|
||||
note
|
||||
description: "Representation of a date at C level"
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date: 2014-03-11 23:16:07 -0400 (Tue, 11 Mar 2014) $"
|
||||
revision: "$Revision: 35 $"
|
||||
|
||||
class
|
||||
C_DATE
|
||||
|
||||
-- This is a copy of C_DATE from ISE's time cluster. I copied
|
||||
-- it to my support cluster so I can use it in my temporal and
|
||||
-- other projects without the overhead of using all of ISE's
|
||||
-- time cluster.
|
||||
|
||||
inherit
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
make_utc
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance of C_DATA using current local time.
|
||||
do
|
||||
is_utc := False
|
||||
update
|
||||
end
|
||||
|
||||
make_utc
|
||||
-- Create an instance of C_DATE holding UTC values.
|
||||
do
|
||||
is_utc := True
|
||||
update
|
||||
ensure
|
||||
is_utc: is_utc
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_utc: BOOLEAN
|
||||
-- Is Current holding value in UTC format?
|
||||
|
||||
feature -- Update
|
||||
|
||||
update
|
||||
-- Pointer to `struct tm' area.
|
||||
local
|
||||
l_timeb, l_tm, l_time: POINTER
|
||||
l_milli: INTEGER
|
||||
do
|
||||
l_timeb := l_timeb.memory_alloc (timeb_structure_size)
|
||||
l_time := l_time.memory_alloc (time_t_structure_size)
|
||||
ftime (l_timeb)
|
||||
get_time (l_timeb, l_time)
|
||||
if is_utc then
|
||||
l_tm := gmtime (l_time)
|
||||
else
|
||||
l_tm := localtime (l_time)
|
||||
end
|
||||
create internal_item.make_from_pointer (l_tm, tm_structure_size)
|
||||
|
||||
l_milli := get_millitm (l_timeb)
|
||||
if l_milli < 0 or l_milli > 999 then
|
||||
millisecond_now := 0
|
||||
else
|
||||
millisecond_now := l_milli
|
||||
end
|
||||
|
||||
l_timeb.memory_free
|
||||
l_time.memory_free
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
year_now: INTEGER
|
||||
-- Current year at creation time or after last call to `update'.
|
||||
do
|
||||
Result := 1900 + get_tm_year (internal_item.item)
|
||||
ensure
|
||||
year_valid: Result >= 1900
|
||||
end
|
||||
|
||||
month_now: INTEGER
|
||||
-- Current month at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_mon (internal_item.item) + 1
|
||||
ensure
|
||||
month_valid: Result >= 1 and Result <= 12
|
||||
end
|
||||
|
||||
day_now: INTEGER
|
||||
-- Current day at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_mday (internal_item.item)
|
||||
ensure
|
||||
day_valid: Result >= 1 and Result <= 31
|
||||
end
|
||||
|
||||
hour_now: INTEGER
|
||||
-- Current hour at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_hour (internal_item.item)
|
||||
ensure
|
||||
hour_valid: Result >= 0 and Result <= 23
|
||||
end
|
||||
|
||||
minute_now: INTEGER
|
||||
-- Current minute at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_min (internal_item.item)
|
||||
ensure
|
||||
minute_valid: Result >= 0 and Result <= 59
|
||||
end
|
||||
|
||||
second_now: INTEGER
|
||||
-- Current second at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_sec (internal_item.item)
|
||||
if Result > 59 then
|
||||
-- Some platform returns up to 61 for leap seconds.
|
||||
Result := 59
|
||||
end
|
||||
ensure
|
||||
second_valid: Result >= 0 and Result <= 59
|
||||
end
|
||||
|
||||
millisecond_now: INTEGER
|
||||
-- Current millisecond at creation time or after last call to `update'.
|
||||
|
||||
feature {NONE} -- Externals
|
||||
|
||||
ftime (p: POINTER)
|
||||
-- Set current date and time in `p', pointer to a `struct timeb' area.
|
||||
external
|
||||
"C macro signature (struct timeb*) use <sys/timeb.h>"
|
||||
end
|
||||
|
||||
feature {NONE} -- `struct timeb' encapsulation
|
||||
|
||||
timeb_structure_size: INTEGER
|
||||
-- Size of `struct timeb'.
|
||||
external
|
||||
"C macro use <sys/timeb.h>"
|
||||
alias
|
||||
"sizeof(struct timeb)"
|
||||
end
|
||||
|
||||
time_t_structure_size: INTEGER
|
||||
-- Size of `struct timeb'.
|
||||
external
|
||||
"C macro use <time.h>"
|
||||
alias
|
||||
"sizeof(time_t)"
|
||||
end
|
||||
|
||||
tm_structure_size: INTEGER
|
||||
-- Size of `struct tm'.
|
||||
external
|
||||
"C macro use <time.h>"
|
||||
alias
|
||||
"sizeof(struct tm)"
|
||||
end
|
||||
|
||||
get_millitm (p: POINTER): INTEGER
|
||||
-- Get `p->millitm'.
|
||||
external
|
||||
"C struct struct timeb access millitm use <sys/timeb.h>"
|
||||
end
|
||||
|
||||
get_time (p, t: POINTER)
|
||||
-- Get `p->time'.
|
||||
external
|
||||
"C inline use <sys/timeb.h>, <time.h>"
|
||||
alias
|
||||
"*(time_t *) $t = (((struct timeb *)$p)->time);"
|
||||
end
|
||||
|
||||
feature {NONE} -- `struct tm' encapsulation
|
||||
|
||||
internal_item: MANAGED_POINTER
|
||||
-- Pointer to `struct tm' area.
|
||||
|
||||
localtime (t: POINTER): POINTER
|
||||
-- Pointer to `struct tm' area.
|
||||
external
|
||||
"C inline use <time.h>"
|
||||
alias
|
||||
"localtime ((time_t *) $t)"
|
||||
end
|
||||
|
||||
gmtime (t: POINTER): POINTER
|
||||
-- Pointer to `struct tm' area in UTC.
|
||||
external
|
||||
"C inline use <time.h>"
|
||||
alias
|
||||
"gmtime ((time_t *) $t)"
|
||||
end
|
||||
|
||||
get_tm_year (p: POINTER): INTEGER
|
||||
-- Get `p->tm_year', number of years since 1900.
|
||||
external
|
||||
"C struct struct tm access tm_year use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_mon (p: POINTER): INTEGER
|
||||
-- Get `p->tm_mon'.
|
||||
external
|
||||
"C struct struct tm access tm_mon use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_mday (p: POINTER): INTEGER
|
||||
-- Get `p->tm_mday'.
|
||||
external
|
||||
"C struct struct tm access tm_mday use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_hour (p: POINTER): INTEGER
|
||||
-- Get `p->tm_hour'.
|
||||
external
|
||||
"C struct struct tm access tm_hour use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_min (p: POINTER): INTEGER
|
||||
-- Get `p->tm_min'.
|
||||
external
|
||||
"C struct struct tm access tm_min use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_sec (p: POINTER): INTEGER
|
||||
-- Get `p->tm_sec'.
|
||||
external
|
||||
"C struct struct tm access tm_sec use <time.h>"
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2006, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
356 Storke Road, Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
|
||||
|
||||
|
||||
|
||||
end -- class C_DATE
|
34
jj_temporal/classes/hms_constants.e
Normal file
34
jj_temporal/classes/hms_constants.e
Normal file
@ -0,0 +1,34 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with HMS_TIME, HMS_DURATION, and HMS_INTERVAL.
|
||||
]"
|
||||
date: "24 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
|
||||
class
|
||||
HMS_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_second: HMS_DURATION
|
||||
once
|
||||
create Result.set (0, 0, 1)
|
||||
end
|
||||
|
||||
One_minute: HMS_DURATION
|
||||
once
|
||||
create Result.set (0, 1, 0)
|
||||
end
|
||||
|
||||
One_hour: HMS_DURATION
|
||||
once
|
||||
create Result.set (1, 0, 0)
|
||||
end
|
||||
|
||||
end -- class HMS_CONSTANTS
|
281
jj_temporal/classes/hms_duration.e
Normal file
281
jj_temporal/classes/hms_duration.e
Normal file
@ -0,0 +1,281 @@
|
||||
note
|
||||
description: "[
|
||||
A duration of time represented by hours, minutes, and seconds.
|
||||
]"
|
||||
names: "duration, time_duration"
|
||||
date: "1999/01/01"; updated: "14 Aug 04"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_DURATION
|
||||
|
||||
create
|
||||
default_create,
|
||||
set,
|
||||
set_fine
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := hours.out + ":" + minutes.out + ":" + seconds.out + "." + milliseconds.out
|
||||
end
|
||||
|
||||
hours: INTEGER
|
||||
-- The number of hours in this DURATION
|
||||
|
||||
minutes: INTEGER
|
||||
-- The number of minutes in this DURATION
|
||||
|
||||
seconds: INTEGER
|
||||
-- The number of seconds in this DURATION
|
||||
|
||||
milliseconds: INTEGER
|
||||
-- The number of milli-seconds in this DURATION
|
||||
|
||||
as_hours: DOUBLE
|
||||
-- Length of this duration in hours.
|
||||
do
|
||||
Result := hours + minutes / 60 + seconds / 3600 + milliseconds / 3600000
|
||||
end
|
||||
|
||||
as_minutes: DOUBLE
|
||||
-- Length of this duration in minutes.
|
||||
do
|
||||
Result := hours * 60 + minutes + seconds / 60 + milliseconds / 60000
|
||||
end
|
||||
|
||||
as_seconds: DOUBLE
|
||||
-- Length of this duration in seconds.
|
||||
do
|
||||
Result := hours * 3600 + minutes * 60 + seconds + milliseconds / 1000
|
||||
end
|
||||
|
||||
as_milliseconds: DOUBLE
|
||||
-- Length of this duration in milliseconds
|
||||
do
|
||||
Result := hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for '*' and '/'.
|
||||
do
|
||||
create Result.set_fine (1, 1, 1, 1)
|
||||
ensure then
|
||||
result_hours_is_one: Result.hours = 1
|
||||
result_minutes_is_one: Result.minutes = 1
|
||||
result_seconds_is_one: Result.seconds = 1
|
||||
result_millisecons_is_one: Result.milliseconds = 1
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for '+' and '-'.
|
||||
do
|
||||
create Result
|
||||
ensure then
|
||||
result_hours_is_zero: Result.hours = 0
|
||||
result_minutes_is_zero: Result.minutes = 0
|
||||
result_seconds_is_zero: Result.seconds = 0
|
||||
result_milliseconds_is_zero: Result.milliseconds = 0
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
do
|
||||
-- Used minutes because it seemed reasonable accuracy.
|
||||
Result := as_minutes / other.as_minutes
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_zero
|
||||
-- Make current have zero length.
|
||||
do
|
||||
set_fine (0, 0, 0, 0)
|
||||
end
|
||||
|
||||
set (a_hours, a_minutes, a_seconds: INTEGER)
|
||||
-- Change the hours, minutes, and seconds to these values
|
||||
-- and set milliseconds to zero.
|
||||
do
|
||||
set_fine (a_hours, a_minutes, a_seconds, 0)
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
minutes_set: minutes = a_minutes
|
||||
seconds_set: seconds = a_seconds
|
||||
milliseconds_zero: milliseconds = 0
|
||||
end
|
||||
|
||||
set_fine (a_hours, a_minutes, a_seconds, a_milliseconds: INTEGER)
|
||||
-- Change `hours', `minutes', `seconds', and `milliseconds'
|
||||
do
|
||||
hours := a_hours
|
||||
minutes := a_minutes
|
||||
seconds := a_seconds
|
||||
milliseconds := a_milliseconds
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
minutes_set: minutes = a_minutes
|
||||
seconds_set: seconds = a_seconds
|
||||
milliseconds_set: milliseconds = a_milliseconds
|
||||
end
|
||||
|
||||
set_hours (a_hours: INTEGER)
|
||||
-- Change hours
|
||||
do
|
||||
hours := a_hours
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
end
|
||||
|
||||
set_minutes (a_minutes: INTEGER)
|
||||
-- change minutes
|
||||
do
|
||||
minutes := a_minutes
|
||||
ensure
|
||||
minutes_set: minutes = a_minutes
|
||||
end
|
||||
|
||||
set_seconds (a_seconds: INTEGER)
|
||||
-- Change seconds
|
||||
do
|
||||
seconds := a_seconds
|
||||
ensure
|
||||
seconds_set: seconds = a_seconds
|
||||
end
|
||||
|
||||
negate
|
||||
-- Reverses the sign for hours, minutes, and seconds.
|
||||
do
|
||||
hours := -hours
|
||||
minutes := -minutes
|
||||
seconds := -seconds
|
||||
milliseconds := -milliseconds
|
||||
ensure then
|
||||
hours_negated: -hours = old hours
|
||||
minutes_negated: -minutes = old minutes
|
||||
seconds_negated: -seconds = old seconds
|
||||
milliseconds_negated: milliseconds = -milliseconds
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "61 minutes" becomes "1 hour, 1 minute".
|
||||
do
|
||||
-- Fix me !!! for negatives...
|
||||
seconds := seconds + milliseconds // 999
|
||||
milliseconds := milliseconds \\ 999
|
||||
minutes := minutes + seconds // 60
|
||||
seconds := seconds \\ 60
|
||||
hours := hours + minutes // 60
|
||||
minutes := minutes \\ 60
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add 'other'. Does not 'normalize'.
|
||||
do
|
||||
hours := hours + other.hours
|
||||
minutes := minutes + other.minutes
|
||||
seconds := seconds + other.seconds
|
||||
milliseconds := milliseconds + other.milliseconds
|
||||
ensure then
|
||||
hours_added: hours = old hours + other.hours
|
||||
minutes_added: minutes = old minutes + other.minutes
|
||||
seconds_added: seconds = old seconds + other.seconds
|
||||
milliseconds_added: milliseconds = old milliseconds + other.milliseconds
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract 'other'. Does not 'normalize'.
|
||||
do
|
||||
hours := hours - other.hours
|
||||
minutes := minutes - other.minutes
|
||||
seconds := seconds - other.seconds
|
||||
milliseconds := milliseconds - other.milliseconds
|
||||
ensure then
|
||||
hours_subbed: hours = old hours - other.hours
|
||||
minutes_subbed: minutes = old minutes - other.minutes
|
||||
seconds_subbed: seconds = old seconds - other.seconds
|
||||
milliseconds_subbed: milliseconds = old milliseconds - other.milliseconds
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
-- Multiply `hours'
|
||||
v := hours * r
|
||||
hours := v.floor
|
||||
fract := v - hours
|
||||
-- Multiply `minutes' and add fractional of hour
|
||||
v := minutes * r + 60 * fract
|
||||
minutes := v.floor
|
||||
fract := v - minutes
|
||||
-- Mulitply `seconds' and add fractional minute
|
||||
v := seconds * r + 60 * fract
|
||||
seconds := v.floor
|
||||
fract := v - seconds
|
||||
-- Multiply `milliseconds' and add fractional second
|
||||
v := milliseconds * r + 1000 * fract
|
||||
milliseconds := v.rounded
|
||||
-- Normalize
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set_fine (0, 0, 0, (as_milliseconds / r).rounded)
|
||||
normalize
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_seconds.truncated_to_integer // i)
|
||||
normalize
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_seconds.truncated_to_integer \\ i)
|
||||
normalize
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is 'Current' less than 'other'?
|
||||
local
|
||||
temp, temp_other: like Current
|
||||
do
|
||||
temp := twin
|
||||
temp_other := other.twin
|
||||
temp.normalize
|
||||
temp_other.normalize
|
||||
Result := (temp.hours < temp_other.hours) or
|
||||
(temp.hours = temp_other.hours and temp.minutes < temp_other.minutes) or
|
||||
(temp.hours = temp_other.hours and temp.minutes = temp_other.minutes and temp.seconds < temp_other.seconds)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
68
jj_temporal/classes/hms_interval.e
Normal file
68
jj_temporal/classes/hms_interval.e
Normal file
@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time
|
||||
and duration described in terms of hours, minutes, and
|
||||
seconds. Positive durations only.
|
||||
]"
|
||||
names: "hms_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance starting and ending at the default creation
|
||||
-- value for the type of `start' time, having zero length duration.
|
||||
do
|
||||
-- Can't define `default_create' in ABSTRACT_INTERVAL because there
|
||||
-- `start_imp' is deffered and cannot call create on a deferred type.
|
||||
create start_imp
|
||||
finish_imp := start_imp.twin
|
||||
ensure then
|
||||
same_start_and_finish: equal (start, finish)
|
||||
zero_duration: duration.is_zero
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
551
jj_temporal/classes/hms_time.e
Normal file
551
jj_temporal/classes/hms_time.e
Normal file
@ -0,0 +1,551 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time as on a clock. An
|
||||
Hour, Minute, Second time (ie. a time).
|
||||
]"
|
||||
names: "time"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIME
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_TIME
|
||||
rename
|
||||
as_integer as as_seconds
|
||||
redefine
|
||||
default_create,
|
||||
is_valid,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
set,
|
||||
set_fine,
|
||||
from_seconds,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with time 00:00:00 (i.e. midnight).
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
hour: INTEGER
|
||||
-- Hour part of time.
|
||||
|
||||
minute: INTEGER
|
||||
-- Minute part of time.
|
||||
|
||||
second: INTEGER
|
||||
-- Second part of time.
|
||||
|
||||
millisecond: INTEGER
|
||||
-- Millisecond part of the time.
|
||||
|
||||
overflow: INTEGER
|
||||
-- Number of days after a normalize (49 hours gives 2 days overflow).
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string with no seperator characters, such
|
||||
-- as ":", "-", or "/". The time 23:59:59.999 becomes "235959.999"
|
||||
do
|
||||
create Result.make (10)
|
||||
if not (hour >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (hour.out)
|
||||
if not (minute >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (minute.out)
|
||||
if not (second >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (second.out)
|
||||
Result.append (".")
|
||||
if not (millisecond >= 100) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (millisecond >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (millisecond.out)
|
||||
end
|
||||
|
||||
as_seconds: INTEGER
|
||||
-- The number of seconds from midnight to the current time.
|
||||
-- `Millisecond' is rounded.
|
||||
do
|
||||
Result := hour * 60 * 60 + minute * 60 + second + (millisecond / 1000).rounded
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
h, m, s, mil: INTEGER
|
||||
do
|
||||
h := a_string.substring (1, 2).to_integer
|
||||
m := a_string.substring (3, 4).to_integer
|
||||
s := a_string.substring (5, 6).to_integer
|
||||
mil := a_string.substring (8, 10).to_integer
|
||||
set_fine (h, m, s, mil)
|
||||
end
|
||||
|
||||
from_seconds (a_seconds: INTEGER)
|
||||
-- Initialize as `a_seconds' from midnight.
|
||||
do
|
||||
set (0, 0, 0)
|
||||
add_seconds (a_seconds)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Set current time according to timezone, setting `millisecond' to zero.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, 0)
|
||||
end
|
||||
|
||||
set_now_fine
|
||||
-- Set current time according to timezone, including milli-seconds.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, C_date.millisecond_now)
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- The `millisecond' is set to zero.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.hour_now, C_date.minute_now, C_date.second_now)
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format, including `millisecond'.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, C_date.millisecond_now)
|
||||
end
|
||||
|
||||
set (h, m, s: INTEGER)
|
||||
-- Change the hour, minute, and second.
|
||||
-- Set `millisecond' to 0.
|
||||
require
|
||||
hour_valid: 0 <= h and h <= 23;
|
||||
minute_valid: 0 <= m and m <= 59;
|
||||
second_valid: 0 <= s and s <= 59
|
||||
do
|
||||
set_fine (h, m, s, 0)
|
||||
ensure
|
||||
hour_assigned: hour = h
|
||||
minute_assigned: minute = m
|
||||
second_assigned: second = s
|
||||
millisecond_assigned: millisecond = 0
|
||||
end
|
||||
|
||||
set_fine (h, m, s, mil: INTEGER)
|
||||
-- Change the hour, minute, and second
|
||||
require
|
||||
hour_valid: 0 <= h and h <= 23
|
||||
minute_valid: 0 <= m and m <= 59
|
||||
second_valid: 0 <= s and s <= 59
|
||||
millisecond_valid: 0 <= mil and mil <= 999999
|
||||
do
|
||||
hour := h;
|
||||
minute := m;
|
||||
second := s;
|
||||
millisecond := mil
|
||||
ensure
|
||||
hour_assigned: hour = h
|
||||
minute_assigned: minute = m
|
||||
second_assigned: second = s
|
||||
millisecond_assigned: millisecond = mil
|
||||
end
|
||||
|
||||
set_hour (a_hour: INTEGER)
|
||||
-- Change the `hour'.
|
||||
require
|
||||
hour_valid: 0 <= a_hour and a_hour <= 23;
|
||||
do
|
||||
hour := a_hour
|
||||
ensure
|
||||
hour_assigned: hour = a_hour
|
||||
end
|
||||
|
||||
set_minute (a_minute: INTEGER)
|
||||
-- Change the `minute'.
|
||||
require
|
||||
minute_valid: 0 <= a_minute and a_minute <= 59;
|
||||
do
|
||||
minute := a_minute
|
||||
ensure
|
||||
minute_assigned: minute = a_minute
|
||||
end
|
||||
|
||||
set_second (a_second: INTEGER)
|
||||
-- Change the second.
|
||||
require
|
||||
second_valid: 0 <= a_second and a_second <= 59
|
||||
do
|
||||
second := a_second
|
||||
ensure
|
||||
second_assigned: second = a_second
|
||||
end
|
||||
|
||||
set_millisecond (a_millisecond: INTEGER)
|
||||
-- Change the `millisecond'
|
||||
require
|
||||
valid_millisecond: 0 <= a_millisecond and a_millisecond <= 999
|
||||
do
|
||||
millisecond := a_millisecond
|
||||
ensure
|
||||
millisecond_assigned: millisecond = a_millisecond
|
||||
end
|
||||
|
||||
from_integer (a_integer: INTEGER)
|
||||
-- Change Current to the time represented by `a_integer'.
|
||||
-- `A_compact_time' must represent a date that is not BC.
|
||||
do
|
||||
-- Fix me !!!
|
||||
end
|
||||
|
||||
clear_overflow
|
||||
-- Remove the `overflow' condition by seting overflow to 0.
|
||||
-- (Overflows occur when `add_duration' causes the time to be past 23:59:59.999)
|
||||
do
|
||||
overflow := 0
|
||||
end
|
||||
|
||||
truncate_to_hours
|
||||
-- Reset "to the hour" (set minutes and seconds to 0).
|
||||
do
|
||||
set_fine (hour, 0, 0, 0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
truncate_to_minutes
|
||||
-- Reset "to the minute" (i.e. set seconds to 0.)
|
||||
do
|
||||
set_fine (hour, minute, 0, 0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_unchanged: minute = old minute
|
||||
second_zero: second = 0
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
truncate_to_seconds
|
||||
-- Set the `millisecond' to zero.
|
||||
-- Use when `millisecond' portion is to be ignored.
|
||||
do
|
||||
set_millisecond (0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_unchanged: minute = old minute
|
||||
second_unchaged: second = old second
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this time come before 'other'?
|
||||
require else
|
||||
other_time_not_void: other /= Void
|
||||
do
|
||||
Result := hour < other.hour or else
|
||||
(hour = other.hour) and (minute < other.minute) or else
|
||||
(hour = other.hour) and (minute = other.minute) and (second < other.second) or else
|
||||
(hour = other.hour) and (minute = other.minute) and (second = other.second) and (millisecond < other.millisecond)
|
||||
ensure then
|
||||
-- definition: Result = (hour < other.hour) or else
|
||||
-- (hour = other.hour) and (minute < other.minute) or else
|
||||
-- (hour = other.hour) and (minute = other.minute) and (second < other.second) or else
|
||||
-- (hour = other.hour) and (minute = other.minute) and (second = other.second) and (millisecond < other.millisecond)
|
||||
end
|
||||
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_duration (a_duration: like Duration_anchor)
|
||||
-- Add a length of time (in hours, minutes, and seconds) to the time.
|
||||
do
|
||||
-- hour := hour + a_duration.hours
|
||||
-- minute := minute + a_duration.minutes
|
||||
-- second := second + a_duration.seconds
|
||||
-- millisecond := millisecond + a_duration.milliseconds
|
||||
add_milliseconds (a_duration.milliseconds)
|
||||
add_seconds (a_duration.seconds)
|
||||
add_minutes (a_duration.minutes)
|
||||
add_hours (a_duration.hours)
|
||||
end
|
||||
|
||||
add_hours (a_number: INTEGER)
|
||||
-- Add `a_number' of hours to the current time
|
||||
local
|
||||
h: INTEGER
|
||||
do
|
||||
h := a_number \\ 24
|
||||
hour := hour + h
|
||||
check
|
||||
number_now_even: (a_number - h) \\ 24 = 0
|
||||
end
|
||||
overflow := (a_number - h) // 24
|
||||
if hour < 0 then
|
||||
check
|
||||
positive_overflow: overflow >= 1
|
||||
end
|
||||
hour := hour + 24
|
||||
overflow := overflow - 1
|
||||
end
|
||||
if hour >= 24 then
|
||||
hour := hour - 24
|
||||
overflow := overflow + 1
|
||||
end
|
||||
end
|
||||
|
||||
add_minutes (a_number: INTEGER)
|
||||
-- Add `a_number' of minutes to the current time.
|
||||
local
|
||||
m: INTEGER
|
||||
do
|
||||
minute := minute + a_number
|
||||
m := minute
|
||||
minute := minute \\ 60
|
||||
if minute < 0 then
|
||||
minute := minute + 60
|
||||
add_hours (-1)
|
||||
end
|
||||
add_hours (m // 60)
|
||||
end
|
||||
|
||||
add_seconds (a_number: INTEGER)
|
||||
-- Add `a_number' of seconds to the current time.
|
||||
local
|
||||
s: INTEGER
|
||||
do
|
||||
second := second + a_number
|
||||
s := second
|
||||
second := second \\ 60
|
||||
if second < 0 then
|
||||
second := second + 60
|
||||
add_minutes (-1)
|
||||
end
|
||||
add_minutes (s // 60)
|
||||
end
|
||||
|
||||
add_milliseconds (a_number: INTEGER)
|
||||
-- Add `a_number' of milliseconds to the current time.
|
||||
local
|
||||
ms: INTEGER
|
||||
do
|
||||
millisecond := millisecond + a_number
|
||||
ms := millisecond
|
||||
millisecond := millisecond \\ 1000
|
||||
if millisecond < 0 then
|
||||
millisecond := millisecond + 1000
|
||||
add_seconds (-1)
|
||||
end
|
||||
add_seconds (ms // 1000)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
-- Caveat: the `milliseconds' will be lost due to rounding in `as_seconds'.
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
time_between (other: like Current): like Duration_anchor
|
||||
-- A length of time in hours, minutes, and seconds
|
||||
-- between this time and other.
|
||||
local
|
||||
larger, smaller: like Current
|
||||
h, m, s, ms: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
ms := larger.millisecond - smaller.millisecond
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if ms < 0 then
|
||||
ms := ms + 999
|
||||
s := s - 1
|
||||
end
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
create Result.set_fine (h, m, s, ms)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
seconds_between (a_other: like Current): INTEGER
|
||||
-- The number of seconds between Current and `other'
|
||||
require
|
||||
other_exists: a_other /= Void
|
||||
local
|
||||
larger, smaller: like Current
|
||||
h, m, s, ms: INTEGER
|
||||
do
|
||||
larger := max (a_other)
|
||||
smaller := min (a_other)
|
||||
ms := larger.millisecond - smaller.millisecond
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if ms < 0 then
|
||||
ms := ms + 999
|
||||
s := s - 1
|
||||
end
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
Result := h * 60 * 60 + m * 60 + s
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
hs, ms, ss, mils: STRING
|
||||
h, m, s, mil: INTEGER
|
||||
do
|
||||
if a_string /= Void and then a_string.count = 10 and then equal (a_string.substring (7, 7), ".") then
|
||||
hs := a_string.substring (1, 2)
|
||||
ms := a_string.substring (3, 4)
|
||||
ss := a_string.substring (5, 6)
|
||||
mils := a_string.substring (8, 10)
|
||||
if hs.is_integer and then ms.is_integer and then ss.is_integer and then mils.is_integer then
|
||||
h := hs.to_integer
|
||||
m := ms.to_integer
|
||||
s := ms.to_integer
|
||||
mil := mils.to_integer
|
||||
if (h >= 0 and h <= 23) and then
|
||||
(m >= 0 and m <= 59) and then
|
||||
(s >= 0 and s <= 59) and then
|
||||
(mil >= 0 and mil <= 999) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
do
|
||||
Result := a_integer >= 0
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
-- normalize is
|
||||
-- -- convert to a normal time (1 minute, 60 seconds becomes 2 minutes 0 seconds)
|
||||
-- do
|
||||
-- second := second + millisecond // 999
|
||||
-- millisecond := millisecond \\ 999
|
||||
-- if millisecond < 0 then
|
||||
-- millisecond := millisecond + 999
|
||||
-- second := second - 1
|
||||
-- end
|
||||
-- minute := minute + second // 60
|
||||
-- second := second \\ 60
|
||||
-- if second < 0 then
|
||||
-- second := second + 60
|
||||
-- minute := minute - 1
|
||||
-- end
|
||||
-- hour := hour + minute // 60
|
||||
-- minute := minute \\ 60
|
||||
-- if minute < 0 then
|
||||
-- minute := minute + 60
|
||||
-- hour := hour - 1
|
||||
-- end
|
||||
-- overflow := hour // 24
|
||||
-- hour := hour \\ 24
|
||||
-- if hour < 0 then
|
||||
-- hour := hour + 24
|
||||
-- overflow := overflow - 1
|
||||
-- end
|
||||
-- end
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is time in correct format?
|
||||
do
|
||||
Result := (0 <= millisecond and millisecond <= 999) and
|
||||
(0 <= second and second <= 59) and
|
||||
(0 <= minute and minute <= 59) and
|
||||
(0 <= hour and hour <= 23)
|
||||
ensure then
|
||||
valid_result: Result implies
|
||||
(0 <= millisecond and millisecond <= 999) and
|
||||
(0 <= second and second <= 59) and
|
||||
(0 <= minute and minute <= 59) and
|
||||
(0 <= hour and hour <= 23)
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: HMS_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
74
jj_temporal/classes/hms_timer.e
Normal file
74
jj_temporal/classes/hms_timer.e
Normal file
@ -0,0 +1,74 @@
|
||||
note
|
||||
description: "[
|
||||
Timer for hours, minutes, seconds, and miliseconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_INTERVAL
|
||||
undefine
|
||||
duration,
|
||||
out
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {HMS_INTERVAL}
|
||||
Precursor {TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
60
jj_temporal/classes/time_stampable.e
Normal file
60
jj_temporal/classes/time_stampable.e
Normal file
@ -0,0 +1,60 @@
|
||||
note
|
||||
description: "[
|
||||
Objects which record their creation time.
|
||||
]"
|
||||
date: "1 Sep 04"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
TIME_STAMPABLE
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
create timestamp.set_now_utc_fine
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
id: STRING
|
||||
-- Unique (hopefully) object id based on the creation time of the object.
|
||||
-- Concatination of Current's `generating_type' and `time_stamp'.
|
||||
do
|
||||
Result := generating_type.name.to_string_8 + " " + timestamp.as_string
|
||||
end
|
||||
|
||||
timestamp: YMDHMS_TIME
|
||||
-- Time this object was created
|
||||
|
||||
--feature -- Comparison
|
||||
|
||||
-- infix "<" (a_other: like Current): BOOLEAN is
|
||||
-- -- Is Current less than `a_other'?
|
||||
-- do
|
||||
-- Result := id < a_other.id
|
||||
---- Result := timestamp < a_other.timestamp
|
||||
-- end
|
||||
|
||||
invariant
|
||||
|
||||
time_stamp_exists: timestamp /= Void
|
||||
|
||||
end
|
122
jj_temporal/classes/timer.e
Normal file
122
jj_temporal/classes/timer.e
Normal file
@ -0,0 +1,122 @@
|
||||
note
|
||||
description: "[
|
||||
Stop-watch type object.
|
||||
Create the object and call `reset' to use.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
TIMER
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
duration
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Initialize Current
|
||||
do
|
||||
create lap_times.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
duration: like duration_anchor
|
||||
-- The time between the `start' and the `finish';
|
||||
-- or the time between the `start' and the current time if
|
||||
-- the timer is running.
|
||||
local
|
||||
t: like time_anchor
|
||||
do
|
||||
if is_running then
|
||||
t := finish
|
||||
t.set_now_utc_fine
|
||||
Result := t.time_between (start)
|
||||
else
|
||||
Result := Precursor
|
||||
end
|
||||
end
|
||||
|
||||
cumulative: like duration_anchor
|
||||
-- Cumulative total of all the times elapsed on the timer.
|
||||
-- Recalculated at every `stop'.
|
||||
|
||||
i_th_lap (a_index: INTEGER): like duration_anchor
|
||||
-- The `a_index'th duration.
|
||||
require
|
||||
is_valid_lap_index: is_valid_lap_index (a_index)
|
||||
do
|
||||
Result := lap_times.i_th (a_index)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_running: BOOLEAN
|
||||
-- Is the timer running?
|
||||
-- (Use `start' to begin timing and `stop' to end.)
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
reset
|
||||
-- Reset `elapsed' to zero.
|
||||
do
|
||||
start_imp.set_now_utc_fine
|
||||
finish_imp.copy (start)
|
||||
cumulative.set_zero
|
||||
lap_times.wipe_out
|
||||
end
|
||||
|
||||
run
|
||||
-- Start the timer
|
||||
require
|
||||
not_running: not is_running
|
||||
do
|
||||
is_running := True
|
||||
start_imp.set_now_utc_fine
|
||||
ensure
|
||||
is_running: is_running
|
||||
end
|
||||
|
||||
stop
|
||||
-- Stop the timer
|
||||
require
|
||||
is_running: is_running
|
||||
do
|
||||
is_running := False
|
||||
finish_imp.set_now_utc_fine
|
||||
cumulative := cumulative + duration
|
||||
-- start_imp.copy (finish)
|
||||
-- mark_lap
|
||||
ensure
|
||||
is_stopped: not is_running
|
||||
end
|
||||
|
||||
mark_lap
|
||||
-- Record the current `lap' time in `lap_times' but keep the timer running.
|
||||
do
|
||||
lap_times.extend (duration)
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_valid_lap_index (a_index: INTEGER): BOOLEAN
|
||||
-- Is `a_index' a valid value into the list of `lap_times'?
|
||||
do
|
||||
Result := lap_times.valid_index (a_index)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
lap_times: ARRAYED_LIST [like duration_anchor]
|
||||
-- List of durations for each time `mark_lap' was called.
|
||||
|
||||
end
|
48
jj_temporal/classes/ymd_constants.e
Normal file
48
jj_temporal/classes/ymd_constants.e
Normal file
@ -0,0 +1,48 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with YMD_TIME, YMD_DURATION, and YMD_INTERVAL.
|
||||
]"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_day: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 1)
|
||||
end
|
||||
|
||||
One_week: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 7)
|
||||
end
|
||||
|
||||
One_month: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 1, 0)
|
||||
end
|
||||
|
||||
One_quarter: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 3, 0)
|
||||
end
|
||||
|
||||
One_year: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (1, 0, 0)
|
||||
end
|
||||
|
||||
end -- class YMD_CONSTANTS
|
325
jj_temporal/classes/ymd_duration.e
Normal file
325
jj_temporal/classes/ymd_duration.e
Normal file
@ -0,0 +1,325 @@
|
||||
note
|
||||
description: "[
|
||||
Duration of time described in years, months, and days.
|
||||
]"
|
||||
names: "ymd_duration"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_DURATION
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with zero length.
|
||||
do
|
||||
days_per_month := default_days_per_month
|
||||
set (0, 0, 0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := years.out + ":" + months.out + ":" + days.out
|
||||
end
|
||||
|
||||
years: INTEGER
|
||||
-- Number of years part.
|
||||
-- Does not consider the months or days.
|
||||
|
||||
months: INTEGER
|
||||
-- Number of months part.
|
||||
-- Does not consider the years or days.
|
||||
|
||||
days: INTEGER
|
||||
-- Number of days part.
|
||||
-- Does not consider the months or years.
|
||||
|
||||
default_days_per_month: DOUBLE = 30.4375
|
||||
-- Default value for 'days_per_month'.
|
||||
-- 365.25 days per year divided by 12 months per year.
|
||||
|
||||
days_per_month: DOUBLE
|
||||
-- Number of days in a month. (28?, 29?, 30?, 31?)
|
||||
-- Value assumed by class to do calculations involving conversion
|
||||
-- from days to months to years.
|
||||
-- Default = 30.4375 days / month.
|
||||
|
||||
days_per_year: DOUBLE
|
||||
-- Number of days in the year. Calculated based on 'days_per_month'.
|
||||
-- Value assumed by class to do calculations involving conversion
|
||||
-- from days to months to years.
|
||||
-- Default = 365.25 days / year.
|
||||
do
|
||||
Result := days_per_month * 12
|
||||
end
|
||||
|
||||
as_years: DOUBLE
|
||||
-- Length of duration in years.
|
||||
do
|
||||
Result := years + months / 12 + days / days_per_year
|
||||
end
|
||||
|
||||
as_months: DOUBLE
|
||||
-- Length of duration in months.
|
||||
do
|
||||
Result := years * 12 + months + days / days_per_month
|
||||
end
|
||||
|
||||
as_days: DOUBLE
|
||||
-- Length of duration in days.
|
||||
do
|
||||
Result := years * days_per_year + months * days_per_month + days
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
do
|
||||
create Result
|
||||
Result.set (1,1,1)
|
||||
ensure then
|
||||
result_years_is_one: Result.years = 1
|
||||
result_months_is_one: Result.months = 1
|
||||
result_days_is_one: Result.days = 1
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
do
|
||||
create Result
|
||||
ensure then
|
||||
result_years_is_zero: Result.years = 0
|
||||
result_months_is_zero: Result.months = 0
|
||||
result_days_is_zero: Result.days = 0
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
-- For example: is current duration at least twice as long as other?
|
||||
do
|
||||
-- Result := as_months / other.as_months -- Used months because it seemed reasonable accuracy.
|
||||
Result := as_days / other.as_days -- Must use days because of accuracy problems with month length.
|
||||
end
|
||||
|
||||
normalized: like Current
|
||||
-- A copy of Current in a normalized form.
|
||||
do
|
||||
Result := twin
|
||||
Result.normalize
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_zero
|
||||
-- Make Current have zero length.
|
||||
do
|
||||
set (0, 0, 0)
|
||||
end
|
||||
|
||||
set (ys, ms, ds: INTEGER)
|
||||
-- Change the length of years, months, and days.
|
||||
do
|
||||
years := ys
|
||||
months := ms
|
||||
days := ds
|
||||
ensure
|
||||
years_set: years = ys
|
||||
months_set: months = ms
|
||||
days_set: days = ds
|
||||
end
|
||||
|
||||
set_years (ys: INTEGER)
|
||||
-- Change years
|
||||
do
|
||||
years := ys
|
||||
ensure
|
||||
years_set: years = ys
|
||||
end
|
||||
|
||||
set_months (ms: INTEGER)
|
||||
-- Change months
|
||||
do
|
||||
months := ms;
|
||||
ensure
|
||||
months_set: months = ms
|
||||
end
|
||||
|
||||
set_days (ds: INTEGER)
|
||||
-- Change days
|
||||
do
|
||||
days := ds
|
||||
ensure
|
||||
days_set: days = ds
|
||||
end
|
||||
|
||||
set_days_per_month (i: DOUBLE)
|
||||
-- Change 'days_per_month' (value used in calculations
|
||||
-- involving month lenghts).
|
||||
require
|
||||
in_range: i >= 28 and i <= 31
|
||||
do
|
||||
days_per_month := i
|
||||
ensure
|
||||
days_per_month_set: days_per_month = i
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
negate
|
||||
-- Reverse the sign on years, months, and days.
|
||||
do
|
||||
years := -years;
|
||||
months := -months;
|
||||
days := -days
|
||||
ensure then
|
||||
years_negated: -years = old years
|
||||
months_negated: -months = old months
|
||||
days_negated: -days = old days
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "13 months" becomes "1 year, 1 month".
|
||||
-- Month and year length is based on 'days_per_month'.
|
||||
-- This feature is hard to define. For example, is 28 days equal to
|
||||
-- one month? What about 30 days?
|
||||
-- This needs to be fixed.
|
||||
require
|
||||
days_per_month > 0
|
||||
local
|
||||
m, d: DOUBLE
|
||||
dpm: DOUBLE
|
||||
do
|
||||
-- The check on `days_per_month' was necessary because `<' which calls
|
||||
-- this feature must be getting called before the object is fully
|
||||
-- initialized, so at that point `days_per_month' is zero; this check
|
||||
-- prevents that "floating point exception".
|
||||
if days_per_month = 0 then
|
||||
dpm := Default_days_per_month
|
||||
else
|
||||
dpm := days_per_month
|
||||
end
|
||||
d := days
|
||||
m := d / dpm
|
||||
months := months + m.truncated_to_integer
|
||||
m := m - m.truncated_to_integer
|
||||
d := m * dpm
|
||||
days := d.truncated_to_integer
|
||||
-- if (d - days) > 0.5 then
|
||||
-- days := days + 1
|
||||
-- if days > dpm then
|
||||
-- months := months + 1
|
||||
-- end
|
||||
-- end
|
||||
years := years + months // 12
|
||||
months := months \\ 12
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other to current.
|
||||
do
|
||||
years := years + other.years;
|
||||
months := months + other.months;
|
||||
days := days + other.days
|
||||
ensure then
|
||||
years_added: years = old years + other.years
|
||||
months_added: months = old months + other.months
|
||||
days_add: days = old days + other.days
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from current.
|
||||
do
|
||||
years := years - other.years;
|
||||
months := months - other.months;
|
||||
days := days - other.days
|
||||
ensure then
|
||||
years_subbed: years = old years - other.years
|
||||
months_subbed: months = old months - other.months
|
||||
days_subbed: days = old days - other.days
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
v := years * r
|
||||
years := v.floor
|
||||
fract := v - years
|
||||
|
||||
v := months * r + 12 * fract
|
||||
months := v.floor
|
||||
fract := v - months
|
||||
|
||||
v := days * r + days_per_month * fract
|
||||
days := v.rounded
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, (as_days / r).rounded)
|
||||
normalize
|
||||
end
|
||||
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, (as_days / i).truncated_to_integer)
|
||||
normalize
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo of duration with 'i'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_days.truncated_to_integer \\ i)
|
||||
normalize
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is current shorter than other?
|
||||
local
|
||||
temp, temp_other: like Current
|
||||
do
|
||||
temp := twin
|
||||
temp_other := other.twin
|
||||
temp.normalize
|
||||
temp_other.normalize
|
||||
Result := (temp.years < temp_other.years) or else
|
||||
(temp.years = temp_other.years and temp.months < temp_other.months) or else
|
||||
(temp.years = temp_other.years and temp.months = temp_other.months and temp.days < temp_other.days)
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
days_per_month_in_range: days_per_month >= 28 and days_per_month <= 31
|
||||
|
||||
|
||||
end -- class YMD_DURATION
|
||||
|
67
jj_temporal/classes/ymd_interval.e
Normal file
67
jj_temporal/classes/ymd_interval.e
Normal file
@ -0,0 +1,67 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time and duration
|
||||
described in terms of years, months, and days. Positive durations only.
|
||||
]"
|
||||
names: "ymd_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance starting and ending at the default creation
|
||||
-- value for the type of `start' time, having zero length duration.
|
||||
do
|
||||
-- Can't define `default_create' in ABSTRACT_INTERVAL because there
|
||||
-- `start_imp' is deffered and cannot call create on a deferred type.
|
||||
create start_imp
|
||||
finish_imp := start_imp.twin
|
||||
ensure then
|
||||
same_start_and_finish: equal (start, finish)
|
||||
zero_duration: duration.is_zero
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
671
jj_temporal/classes/ymd_time.e
Normal file
671
jj_temporal/classes/ymd_time.e
Normal file
@ -0,0 +1,671 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time as on a gregorian callendar.
|
||||
Has a `Year', `Month', and `Day' (i.e. a date).
|
||||
]"
|
||||
names: "date, time"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_TIME
|
||||
rename
|
||||
as_integer as as_days,
|
||||
from_integer as from_days
|
||||
redefine
|
||||
default_create,
|
||||
is_valid,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set,
|
||||
from_days,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance based on todays date.
|
||||
do
|
||||
set_now
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
year: INTEGER
|
||||
-- Year part of the date.
|
||||
|
||||
month: INTEGER
|
||||
-- Month part of the date.
|
||||
|
||||
day: INTEGER
|
||||
-- Day part of the date.
|
||||
do
|
||||
Result := internal_day
|
||||
if Result > last_day_of_month then
|
||||
Result := last_day_of_month
|
||||
end
|
||||
end
|
||||
|
||||
week_number: INTEGER
|
||||
-- Week of the year containing this date.
|
||||
local
|
||||
d: YMD_TIME
|
||||
first_d: INTEGER -- Jan 1st is on what day?
|
||||
do
|
||||
create d
|
||||
d.set (year, 1, 1)
|
||||
first_d := d.weekday
|
||||
Result := (((julian + first_d - 1 - 1) // 7) + 1)
|
||||
ensure
|
||||
result_large_enough: Result >= 1
|
||||
result_small_enough: Result <= 54 -- 53 ? 54 if leapyear falls just right.
|
||||
end
|
||||
|
||||
last_day_of_month: INTEGER
|
||||
-- Date of last day for current month
|
||||
do
|
||||
inspect
|
||||
month
|
||||
when 2 then
|
||||
if is_leapyear then
|
||||
Result := 29
|
||||
else
|
||||
Result := 28
|
||||
end
|
||||
when 4, 6, 9, 11 then
|
||||
Result := 30
|
||||
else
|
||||
Result := 31
|
||||
end
|
||||
ensure
|
||||
day_in_range: Result >= 28 and Result <= 31
|
||||
good_not_leap: Result = 28 implies (month = 2 and not is_leapyear)
|
||||
good_in_leap: Result = 29 implies (month = 2 and is_leapyear)
|
||||
good_30s: Result = 30 implies (month = 4 or month = 6 or month = 9 or month = 11)
|
||||
good_31s: Result = 31 implies (month=1 or month=3 or month=5 or month=7 or month=8 or month=10 or month=12)
|
||||
end
|
||||
|
||||
days_remaining_this_month: INTEGER
|
||||
-- Number of days from current until end of month.
|
||||
-- Used in some calculations.
|
||||
do
|
||||
Result := last_day_of_month - day
|
||||
ensure
|
||||
valid_result: Result >= 0 and Result < last_day_of_month
|
||||
end
|
||||
|
||||
julian: INTEGER
|
||||
-- Day of the year between 1 and 366
|
||||
local
|
||||
n,i : INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i >= month
|
||||
loop
|
||||
inspect i
|
||||
when 2 then
|
||||
if is_leapyear then
|
||||
n := n + 29
|
||||
else
|
||||
n := n + 28
|
||||
end
|
||||
when 4,6,9,11 then
|
||||
n := n + 30
|
||||
else
|
||||
n := n + 31
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
result := n + day
|
||||
ensure
|
||||
valid_leapyear_result: is_leapyear implies (1 <= Result and Result <= 366)
|
||||
valid_result: not is_leapyear implies (1 <= Result and Result <= 365)
|
||||
end
|
||||
|
||||
|
||||
weekday: INTEGER
|
||||
-- 1 for Sunday, 2 for Monday, etc
|
||||
-- Only works as far back as ~2 Mar 0001. ???
|
||||
local
|
||||
x : INTEGER
|
||||
do
|
||||
x := internal\\7 + 1 + 1
|
||||
if x > 7 then -- it can only be 8
|
||||
x := 1
|
||||
end
|
||||
result := x
|
||||
ensure
|
||||
valid_weekday: 1 <= Result and Result <= 7
|
||||
end
|
||||
|
||||
as_string: STRING
|
||||
-- The date represented as a string with no spaces.
|
||||
-- 18 Jan 2005 would be "20050118".
|
||||
do
|
||||
create Result.make (10)
|
||||
if is_bc then
|
||||
Result.append ("BC")
|
||||
end
|
||||
if not (year.abs >= 1000) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (year.abs >= 100) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (year.abs >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (year.abs.out)
|
||||
if not (month >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (month.out)
|
||||
if not (day >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (day.out)
|
||||
end
|
||||
|
||||
as_days: INTEGER
|
||||
-- The number of days from midnight (00:00:00)
|
||||
-- on 1 Jan 1970 to the beginning Current's `day'.
|
||||
local
|
||||
t: YMD_TIME
|
||||
do
|
||||
create t
|
||||
t.set (1970, 1, 1)
|
||||
Result := days_between (t)
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_days (a_days: INTEGER)
|
||||
-- Change Current to the time represented by `a_days'.
|
||||
-- `A_days' is assumed to be the number of days since 1 Jan 1970.
|
||||
-- `A_days' must represent a date that is not BC
|
||||
do
|
||||
set (1970, 1, 1)
|
||||
add_days (a_days)
|
||||
end
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
d, m, y: INTEGER
|
||||
do
|
||||
y := a_string.substring (1, 4).to_integer
|
||||
m := a_string.substring (5, 6).to_integer
|
||||
d := a_string.substring (7, 8).to_integer
|
||||
set (y, m, d)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Set the current object to today's date.
|
||||
-- This was copied from ISE's DATE class with the one minor change.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- This was copied from ISE's DATE class with the one minor change.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set (a_year, a_month, a_day: INTEGER)
|
||||
-- Give date new year, month, and day.
|
||||
-- If day > num days in month then day will return last day in the month.
|
||||
require
|
||||
realistic_year: a_year /= 0
|
||||
realistic_month: a_month >= 1 and a_month <= 12
|
||||
realistic_day: a_day >= 1 and a_day <= 31
|
||||
do
|
||||
year := a_year
|
||||
month := a_month
|
||||
internal_day := a_day
|
||||
ensure
|
||||
year_assigned: year = a_year
|
||||
month_assigned: month = a_month
|
||||
day_assigned: day = a_day
|
||||
end
|
||||
|
||||
set_year (a_year: INTEGER)
|
||||
-- Change the year.
|
||||
require
|
||||
realistic_year: a_year /= 0
|
||||
do
|
||||
year := a_year
|
||||
ensure
|
||||
year_assigned: year = a_year
|
||||
end
|
||||
|
||||
set_month (a_month: INTEGER)
|
||||
-- Change the month.
|
||||
require
|
||||
realistic_month: a_month >= 1 and a_month <= 12
|
||||
do
|
||||
month := a_month
|
||||
ensure
|
||||
month_assigned: month = a_month
|
||||
end
|
||||
|
||||
set_day (a_day: INTEGER)
|
||||
-- Change the day.
|
||||
-- If a_day > number of days in the month then
|
||||
-- 'day' will be the last day of month.
|
||||
require
|
||||
realistic_day: a_day >= 1 and a_day <= 31
|
||||
do
|
||||
internal_day := a_day
|
||||
ensure
|
||||
day_assigned: day = a_day
|
||||
end
|
||||
|
||||
truncate_to_years
|
||||
-- Set the day to first day of month 1.
|
||||
-- Use when all but the `year' is to be ignored.
|
||||
do
|
||||
set_day (1)
|
||||
set_month (1)
|
||||
ensure
|
||||
year_unchanged: year = old year
|
||||
month_one: month = 1
|
||||
day_one: day = 1
|
||||
end
|
||||
|
||||
truncate_to_months
|
||||
-- Set day to first day of current month.
|
||||
-- Use when the `day' portion of date is to be ignored.
|
||||
do
|
||||
set_day (1)
|
||||
ensure
|
||||
year_unchanged: year = old year
|
||||
month_unchanged: month = old month
|
||||
day_one: day = 1
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_leapyear: BOOLEAN
|
||||
-- Is this a leapyear?
|
||||
do
|
||||
if is_bc then
|
||||
Result := (year + 1) \\ 4 = 0 and not ((year + 1) \\ 400 = 0)
|
||||
else
|
||||
Result := year \\ 4 = 0 and (not (year \\ 100 = 0) or else year \\ 400 = 0)
|
||||
end
|
||||
end
|
||||
|
||||
is_bc: BOOLEAN
|
||||
-- Does the date represent a date B.C. (ie year < 1)
|
||||
do
|
||||
Result := year <= -1
|
||||
ensure
|
||||
definition: Result implies year <= -1
|
||||
end
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
do
|
||||
Result := not is_bc and then
|
||||
(Current >= Minimum_representable_date and Current <= Maximum_representable_date)
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
days_between (other: like Current): INTEGER
|
||||
-- Days between this date and 'other'.
|
||||
-- Only works back to ~2 Mar 0001.
|
||||
require
|
||||
other_exists : other /= Void
|
||||
do
|
||||
Result := (other.internal - internal).abs
|
||||
ensure
|
||||
definition: Result = (other.internal - internal).abs
|
||||
end
|
||||
|
||||
time_between (other: like Current): like Duration_anchor
|
||||
-- The difference between two dates as a duration
|
||||
local
|
||||
larger, smaller: like Current
|
||||
y, m, d: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
y := larger.year - smaller.year
|
||||
m := larger.month - smaller.month
|
||||
d := larger.day - smaller.day
|
||||
if d < 0 then
|
||||
d := d + smaller.last_day_of_month
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 12
|
||||
y := y - 1
|
||||
end
|
||||
create Result
|
||||
Result.set (y, m, d)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
-- Dependent on the `internal' representation of dates.
|
||||
do
|
||||
-- These values were found by trial and error. This will give a
|
||||
-- date from 1 Jan 0001 to 18 Oct 1,469,902, which, I believe, is
|
||||
-- far enough into the future.
|
||||
Result := a_integer >= 1721426 and a_integer <= 538592032
|
||||
ensure then
|
||||
definition: Result implies (a_integer >= 1721426) and then
|
||||
(a_integer <= 538592032) -- dependent on `internal'
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
bcs: detachable STRING
|
||||
ys, ms, ds: STRING
|
||||
y, m, d: INTEGER
|
||||
pad: INTEGER -- add 2 if is "BC"
|
||||
do
|
||||
if a_string /= Void and then (a_string.count = 8 or a_string.count = 10) then
|
||||
if a_string.count = 10 then
|
||||
pad := 2
|
||||
bcs := a_string.substring (1, 2)
|
||||
end
|
||||
ys := a_string.substring (1 + pad, 4 + pad)
|
||||
ms := a_string.substring (5 + pad, 6 + pad)
|
||||
ds := a_string.substring (7 + pad, 8 + pad)
|
||||
if ys.is_integer and then ms.is_integer and then ds.is_integer then
|
||||
y := ys.to_integer
|
||||
m := ms.to_integer
|
||||
d := ds.to_integer
|
||||
if (y /= 0) and then (m >= 0 and m < 12)and then (d >= 0 and d <= 31) then
|
||||
Result := True
|
||||
if bcs /= Void and then not equal (bcs, "BC") then
|
||||
Result := False
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_years (a_num: INTEGER)
|
||||
-- Add 'a_num' number of years to the date. Works for negative numbers also.
|
||||
local
|
||||
y: INTEGER
|
||||
do
|
||||
y := year
|
||||
year := year + a_num
|
||||
if year = 0 then -- Must preserve invarient: year can not be 0.
|
||||
if y < 0 then -- year was less than 0 and increased to 0.
|
||||
year := 1
|
||||
else -- year was greater than 0 and decreased to 0.
|
||||
year := -1
|
||||
end
|
||||
end
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_months (a_num: INTEGER)
|
||||
-- Add 'a_num' number of months to the date. Works for negative numbers also.
|
||||
local
|
||||
m: INTEGER -- store month prior making month valid to call 'add_years'.
|
||||
do
|
||||
month := month + a_num
|
||||
m := month
|
||||
month := month \\ 12 -- preserve invarient
|
||||
if month < 1 then
|
||||
month := month + 12 -- preserve invarient
|
||||
add_years (-1)
|
||||
end
|
||||
add_years (m // 12) -- add a year for every multiple of 12.
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_days (a_num: INTEGER)
|
||||
-- Add 'a_num' number of days to the date. Works for negative numbers also.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
if a_num > 0 then
|
||||
from i := a_num
|
||||
until i <= days_remaining_this_month
|
||||
loop
|
||||
i := i - (days_remaining_this_month + 1)
|
||||
set_day (1)
|
||||
add_months (1)
|
||||
end
|
||||
set_day (day + i)
|
||||
elseif a_num < 0 then
|
||||
from
|
||||
i := a_num.abs
|
||||
until
|
||||
i < day
|
||||
loop
|
||||
i := (day - i).abs
|
||||
add_months (-1)
|
||||
set_day (last_day_of_month)
|
||||
end
|
||||
set_day (day - i)
|
||||
else
|
||||
-- do nothing if a_num = 0
|
||||
end
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_duration (a_duration: like Duration_anchor)
|
||||
-- Add a length of time (in years, months, and days) to the date.
|
||||
do
|
||||
add_days (a_duration.days)
|
||||
add_months (a_duration.months)
|
||||
add_years (a_duration.years)
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this date come before 'other'?
|
||||
require else
|
||||
other_not_void: other /= Void
|
||||
do
|
||||
Result := year < other.year or else
|
||||
(year = other.year) and (month < other.month) or else
|
||||
(year = other.year) and (month = other.month) and (day < other.day)
|
||||
ensure then
|
||||
-- definition: year < other.year or else
|
||||
-- (year = other.year) and (month < other.month) or else
|
||||
-- (year = other.year) and (month = other.month) and (day < other.day)
|
||||
end
|
||||
|
||||
feature {YMD_TIME} -- Implementation
|
||||
|
||||
frozen internal: INTEGER
|
||||
-- Internal representation of YMD_TIME
|
||||
-- Used internally by some features.
|
||||
-- Does not work for BC dates; only works back to 1 January 0001,
|
||||
-- at which time the result is 1,721,426.
|
||||
-- Will work up to a date of 18 Oct 1,469,902 (found by trial).
|
||||
require
|
||||
not_bc: not is_bc
|
||||
local
|
||||
c, ya : INTEGER;
|
||||
d,m,y : INTEGER;
|
||||
do
|
||||
d := day;
|
||||
m := month;
|
||||
y := year;
|
||||
if m > 2 then
|
||||
m := m - 3;
|
||||
else
|
||||
m := m + 9;
|
||||
y := y - 1;
|
||||
end
|
||||
c := y // 100;
|
||||
ya := y - 100 * c;
|
||||
result := (146097 * c) // 4 + (1461 * ya) // 4 + (153 * m + 2) // 5 + d + 1721119;
|
||||
ensure
|
||||
result_large_enough: Result >= 1721426
|
||||
result_small_enough: Result <= 538592032
|
||||
end
|
||||
|
||||
frozen from_internal (num: INTEGER)
|
||||
-- Create a YMD_TIME from an internal representation.
|
||||
local
|
||||
y,m,d,j : INTEGER
|
||||
do
|
||||
j := num;
|
||||
j := j - 1721119
|
||||
y := (4 * j - 1) // 146097; j := 4 * j - 1 - 146097 * y;
|
||||
d := j // 4;
|
||||
j := (4 * d + 3) // 1461; d := 4 * d + 3 - 1461 * j;
|
||||
d := (d + 4) // 4;
|
||||
m := (5 * d - 3) // 153; d := 5 * d - 3 - 153 * m;
|
||||
d := (d + 5) // 5;
|
||||
y := 100 * y + j;
|
||||
if m < 10 then
|
||||
m := m + 3;
|
||||
else
|
||||
m := m - 9;
|
||||
y := y + 1;
|
||||
end;
|
||||
internal_day := d;
|
||||
month := m;
|
||||
year := y;
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_day: INTEGER
|
||||
-- Used to save last day of month if day is greater than 28, 30, or 31.
|
||||
-- Actual day is calculated from this value.
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is the date logical?
|
||||
do
|
||||
Result := is_valid_year and is_valid_month and is_valid_day
|
||||
end
|
||||
|
||||
is_valid_year: BOOLEAN
|
||||
-- Is the year logical?
|
||||
-- Only invalid year is year "0".
|
||||
do
|
||||
Result := year /= 0
|
||||
ensure
|
||||
definition: year /= 0
|
||||
end
|
||||
|
||||
is_valid_month: BOOLEAN
|
||||
-- Is the month logical?
|
||||
do
|
||||
Result := 1 <= month and month <= 12
|
||||
ensure
|
||||
definition: 1 <= month and month <= 12
|
||||
end
|
||||
|
||||
is_valid_day: BOOLEAN
|
||||
-- Is the day logical based on month and year?
|
||||
do
|
||||
Result := day >= 1 and then
|
||||
( (day <= 28) or else
|
||||
((month=4 or month=6 or month=9 or month=11) and then day <= 30) or else
|
||||
((month=1 or month=3 or month=5 or month=7 or month=8 or month=10 or month=12) and then day <= 31) or else
|
||||
(month=2 and is_leapyear and day <= 29) )
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
Minimum_representable_date: like Current
|
||||
-- The earliest date that can be represented as an integer.
|
||||
-- This value is dependent on the implementation of `internal' and
|
||||
-- was found by trial and error to be 1 Jan 0001.
|
||||
do
|
||||
create Result
|
||||
Result.set_year (1)
|
||||
Result.set_month (1)
|
||||
Result.set_day (1)
|
||||
end
|
||||
|
||||
Maximum_representable_date: like Current
|
||||
-- The latest date that can be represented as an integer.
|
||||
-- This value is dependent on the implementation of `internal' and
|
||||
-- was found by trial and error to be 18 Oct 1,469,902.
|
||||
do
|
||||
create Result
|
||||
Result.set_year (1_469_902)
|
||||
Result.set_month (10)
|
||||
Result.set_day (18)
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: YMD_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
is_valid: is_valid
|
||||
|
||||
end -- class YMD_TIME
|
||||
|
||||
|
73
jj_temporal/classes/ymd_timer.e
Normal file
73
jj_temporal/classes/ymd_timer.e
Normal file
@ -0,0 +1,73 @@
|
||||
note
|
||||
description: "[
|
||||
Timer for hours, minutes, seconds, and miliseconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
|
||||
class
|
||||
YMD_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
YMD_INTERVAL
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {YMD_INTERVAL}
|
||||
Precursor {TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
268
jj_temporal/classes/ymdhms_duration.e
Normal file
268
jj_temporal/classes/ymdhms_duration.e
Normal file
@ -0,0 +1,268 @@
|
||||
note
|
||||
description: "[
|
||||
Duration of time described in years, months, days,
|
||||
hours, minutes, and seconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
YMD_DURATION
|
||||
rename
|
||||
set as ymd_set,
|
||||
as_string as as_ymd_string
|
||||
redefine
|
||||
default_create,
|
||||
zero, one,
|
||||
set_zero,
|
||||
as_years, as_months, as_days,
|
||||
add, sub, multiply, divide, div, mod, negate, percent_of,
|
||||
is_less,
|
||||
normalize
|
||||
end
|
||||
|
||||
HMS_DURATION
|
||||
rename
|
||||
set as hms_set,
|
||||
as_string as as_hms_string
|
||||
redefine
|
||||
default_create,
|
||||
zero, one,
|
||||
set_zero,
|
||||
as_hours, as_minutes, as_seconds,
|
||||
add, sub, multiply, divide, div, mod, negate, percent_of,
|
||||
is_less,
|
||||
normalize
|
||||
select
|
||||
as_hms_string
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
Precursor {YMD_DURATION}
|
||||
Precursor {HMS_DURATION}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := as_ymd_string + ":" + as_hms_string
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
do
|
||||
create Result
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
do
|
||||
create Result
|
||||
Result.set (1,1,1,1,1,1)
|
||||
end
|
||||
|
||||
as_years: DOUBLE
|
||||
-- Length of duration in years.
|
||||
do
|
||||
Result := years + months / 12 + days / days_per_year +
|
||||
hours / (24 * days_per_year) + minutes / (60 * 24 * days_per_year) +
|
||||
seconds / (60 * 60 * 24 * days_per_year)
|
||||
end
|
||||
|
||||
as_months: DOUBLE
|
||||
-- Length of duration in months.
|
||||
do
|
||||
Result := years * 12 + months + days / days_per_month +
|
||||
hours / hours_per_month + minutes / (60 * hours_per_month) +
|
||||
seconds / (60 * 60 * hours_per_month)
|
||||
end
|
||||
|
||||
as_days: DOUBLE
|
||||
-- Length of duration in days.
|
||||
do
|
||||
Result := years * days_per_year + months * days_per_month + days +
|
||||
hours / 24 + minutes / (24 * 60) + seconds / (24 * 60 * 60)
|
||||
end
|
||||
|
||||
as_hours: DOUBLE
|
||||
-- Length of this duration in hours.
|
||||
do
|
||||
Result := (years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours + minutes / 60 + seconds / 3600
|
||||
end
|
||||
|
||||
as_minutes: DOUBLE
|
||||
-- Length of this duration in minutes.
|
||||
do
|
||||
Result := ((years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours) -- number of hours
|
||||
* 60 + minutes + seconds / 60
|
||||
end
|
||||
|
||||
as_seconds: DOUBLE
|
||||
-- Length of this duration in seconds.
|
||||
do
|
||||
Result := (((years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours) -- number of hours
|
||||
* 60 + minutes) -- number of minutes
|
||||
* 60 + seconds
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set (a_year, a_month, a_day, a_hour, a_minute, a_second: INTEGER)
|
||||
-- Change years, months, days, hours, minutes, seconds.
|
||||
do
|
||||
ymd_set (a_year, a_month, a_day)
|
||||
hms_set (a_hour, a_minute, a_second)
|
||||
ensure
|
||||
years_set: years = a_year
|
||||
months_set: months = a_month
|
||||
days_set: days = a_day
|
||||
hours_set: hours = a_hour
|
||||
minutes_set: minutes = a_minute
|
||||
seconds_set: seconds = a_second
|
||||
end
|
||||
|
||||
set_zero
|
||||
-- Make the duration be zero length.
|
||||
do
|
||||
ymd_set (0, 0, 0)
|
||||
set_fine (0, 0, 0, 0)
|
||||
end
|
||||
|
||||
|
||||
negate
|
||||
-- Reverse the sign for years, ..., seconds.
|
||||
do
|
||||
Precursor {YMD_DURATION}
|
||||
Precursor {HMS_DURATION}
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "13 months" becomes "1 year, 1 month".
|
||||
-- Month and year length is based on 'days_per_month'.
|
||||
do
|
||||
Precursor {HMS_DURATION}
|
||||
set_days (days + hours // 24)
|
||||
set_hours (hours \\ 24)
|
||||
Precursor {YMD_DURATION}
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other to current.
|
||||
do
|
||||
Precursor {YMD_DURATION} (other)
|
||||
Precursor {HMS_DURATION} (other)
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from current.
|
||||
do
|
||||
Precursor {YMD_DURATION} (other)
|
||||
Precursor {HMS_DURATION} (other)
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
v := years * r
|
||||
years := v.floor
|
||||
fract := v - years
|
||||
|
||||
v := months * r + 12 * fract
|
||||
months := v.floor
|
||||
fract := v - months
|
||||
|
||||
v := days * r + days_per_month * fract
|
||||
days := v.floor
|
||||
fract := v - days
|
||||
|
||||
v := hours * r + 24 * fract
|
||||
hours := v.floor
|
||||
fract := v - hours
|
||||
|
||||
v := minutes * r + 60 * fract
|
||||
minutes := v.floor
|
||||
fract := v - minutes
|
||||
|
||||
v := seconds * r + 60 * fract
|
||||
seconds := v.rounded
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (r) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (i) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (i) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
do
|
||||
Result := as_days / other.as_days -- Days seemed reasonable accuracy.
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is this duration shorter than other?
|
||||
do
|
||||
Result := Precursor {YMD_DURATION} (other) or else
|
||||
(years = other.years and then months = other.months and then days = other.days and then
|
||||
Precursor {HMS_DURATION} (other))
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
hours_per_year: DOUBLE
|
||||
-- Number of hours in a year.
|
||||
do
|
||||
Result := days_per_year * 24
|
||||
end
|
||||
|
||||
hours_per_month: DOUBLE
|
||||
-- Number of hours in a month.
|
||||
do
|
||||
Result := days_per_month * 24
|
||||
end
|
||||
|
||||
|
||||
|
||||
end -- class YMDHMS_DURATION
|
||||
|
66
jj_temporal/classes/ymdhms_duration_constants.e
Normal file
66
jj_temporal/classes/ymdhms_duration_constants.e
Normal file
@ -0,0 +1,66 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with {YMDHMS_TIME}, {YMDHMS_DURATION},
|
||||
and {YMDHMS_INTERVAL}.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_second: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 0, 0, 1)
|
||||
end
|
||||
|
||||
One_minute: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 0, 1, 0)
|
||||
end
|
||||
|
||||
One_hour: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 1, 0, 0)
|
||||
end
|
||||
|
||||
One_day: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 1, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_week: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 7, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_month: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 1, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_quarter: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 3, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_year: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (1, 0, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
end -- class YMDHMS_DURATION_CONSTANTS
|
60
jj_temporal/classes/ymdhms_interval.e
Normal file
60
jj_temporal/classes/ymdhms_interval.e
Normal file
@ -0,0 +1,60 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time
|
||||
and duration described in terms of years, months,
|
||||
days, hours, minutes, and seconds. Positive durations only.
|
||||
]"
|
||||
names: "ymdhms_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
HMS_INTERVAL
|
||||
undefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
YMD_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
391
jj_temporal/classes/ymdhms_time.e
Normal file
391
jj_temporal/classes/ymdhms_time.e
Normal file
@ -0,0 +1,391 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time of a particular day. A Year, Month, Day,
|
||||
Hour, Minute, Second - time (ie. a date and time).
|
||||
]"
|
||||
names: "date, time, date_and_time"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_TIME
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME
|
||||
rename
|
||||
set as set_ymd_time,
|
||||
as_days as as_seconds,
|
||||
from_days as from_seconds
|
||||
redefine
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_utc_fine,
|
||||
is_less,
|
||||
is_valid,
|
||||
add_duration,
|
||||
time_between,
|
||||
-- normalize,
|
||||
truncate_to_years,
|
||||
truncate_to_months,
|
||||
as_string,
|
||||
as_seconds,
|
||||
from_seconds,
|
||||
from_string,
|
||||
is_valid_string_representation,
|
||||
is_valid_integer_representation,
|
||||
is_representable_as_integer,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
HMS_TIME
|
||||
rename
|
||||
set as set_hms_time
|
||||
redefine
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
is_less,
|
||||
is_valid,
|
||||
add_duration,
|
||||
time_between,
|
||||
seconds_between,
|
||||
add_hours,
|
||||
-- normalize,
|
||||
truncate_to_hours,
|
||||
truncate_to_minutes,
|
||||
as_string,
|
||||
as_seconds,
|
||||
from_seconds,
|
||||
from_string,
|
||||
is_valid_string_representation,
|
||||
is_valid_integer_representation,
|
||||
is_representable_as_integer,
|
||||
Duration_anchor,
|
||||
Interval_anchor
|
||||
select
|
||||
from_seconds
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
from_seconds,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with todays date at midnight.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- String representation of Current in a compact form.
|
||||
do
|
||||
Result := Precursor {YMD_TIME}
|
||||
Result.append ("T")
|
||||
Result.append (Precursor {HMS_TIME})
|
||||
end
|
||||
|
||||
as_seconds: INTEGER
|
||||
-- The number of seconds from midnight (00:00:00)
|
||||
-- on 1 Jan 1970 to the Current time.
|
||||
local
|
||||
days: INTEGER
|
||||
do
|
||||
days := Precursor {YMD_TIME}
|
||||
Result := days * 24 * 60 * 60 + Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
pos: INTEGER
|
||||
do
|
||||
pos := a_string.index_of ('T', 1)
|
||||
Precursor {YMD_TIME} (a_string.substring (1, pos - 1))
|
||||
Precursor {HMS_TIME} (a_string.substring (pos + 1, a_string.count))
|
||||
end
|
||||
|
||||
from_seconds (a_seconds: INTEGER)
|
||||
-- Change Current to the time represented by `a_seconds'.
|
||||
-- `A_seconds' is assumed to be the number of seconds since 1 Jan 1970.
|
||||
-- It must represent a date that is not BC.
|
||||
do
|
||||
set (1970, 1, 1, 0, 0, 0)
|
||||
add_seconds (a_seconds)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Initialize the instance from the system clock unsing the
|
||||
-- current time zone.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Initialize the instance from the system clock unsing GMT.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
set_now_fine
|
||||
-- Initialize the instance from the system clock using the current
|
||||
-- time zone and including milliseconds.
|
||||
do
|
||||
set_now
|
||||
Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Initialize the instance from the system clock using the GMT and
|
||||
-- including milliseconds.
|
||||
do
|
||||
set_now_utc
|
||||
Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
set (a_year, a_month, a_day, a_hour, a_minute, a_second: INTEGER)
|
||||
-- Change the 'year', ..., 'second'.
|
||||
require
|
||||
year_valid: a_year /= 0;
|
||||
month_valid: 1 <= a_month and a_month <= 12;
|
||||
day_valid: 1 <= a_day and a_day <= 31;
|
||||
hour_valid: 0 <= a_hour and a_hour <= 23;
|
||||
minute_valid: 0 <= a_minute and a_minute <= 59;
|
||||
second_valid: 0 <= a_second and a_second <= 59
|
||||
do
|
||||
set_ymd_time (a_year, a_month, a_day);
|
||||
set_hms_time (a_hour, a_minute, a_second);
|
||||
end
|
||||
|
||||
truncate_to_years
|
||||
-- Set to midnight on the first day of month 1.
|
||||
-- Use when all but the `year' is to be ignored.
|
||||
do
|
||||
Precursor {YMD_TIME}
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_one: month = 1
|
||||
day_one: day = 1
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_months
|
||||
-- Set to midnight on the first day of the current month.
|
||||
-- Use when all but the `year' and `month' is to be ignored.
|
||||
do
|
||||
Precursor {YMD_TIME}
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_unchaged: month = old month
|
||||
day_one: day = 1
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_days
|
||||
-- Set to midnight on the current day.
|
||||
-- Use when the time portion of the date is to be ignored.
|
||||
do
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_unchaged: month = old month
|
||||
day_unchaged: day = old day
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_hours
|
||||
-- Set the `hour', `second', and `millisecond' to zero.
|
||||
-- Used when these portions of the time are to be ignored.
|
||||
do
|
||||
set (year, month, day, hour, 0, 0)
|
||||
end
|
||||
|
||||
truncate_to_minutes
|
||||
do
|
||||
set (year, month, day, hour, minute, 0)
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_duration (a_duration: like duration_anchor)
|
||||
-- Add a length of time (in years, months, days,
|
||||
-- hours, minutes, and seconds) to the time.
|
||||
do
|
||||
Precursor {HMS_TIME} (a_duration)
|
||||
add_days (overflow)
|
||||
clear_overflow
|
||||
Precursor {YMD_TIME} (a_duration)
|
||||
ensure then
|
||||
no_overflowing_days: overflow = 0
|
||||
end
|
||||
|
||||
add_hours (a_number: INTEGER)
|
||||
-- Add `a_number' of hours to the current time
|
||||
do
|
||||
Precursor {HMS_TIME} (a_number)
|
||||
add_days (overflow)
|
||||
clear_overflow
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
do
|
||||
Result := Precursor {HMS_TIME} and then Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
time_between (other: like Current): like duration_anchor
|
||||
-- The difference between two dates as a time span or duration.
|
||||
local
|
||||
larger, smaller: like Current
|
||||
y, mon, d, h, m, s: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
y := larger.year - smaller.year
|
||||
mon := larger.month - smaller.month
|
||||
d := larger.day - smaller.day
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
if h < 0 then
|
||||
h := h + 24
|
||||
d := d - 1
|
||||
end
|
||||
if d < 0 then
|
||||
d := d + smaller.last_day_of_month
|
||||
mon := mon - 1
|
||||
end
|
||||
if mon < 0 then
|
||||
mon := mon + 12
|
||||
y := y - 1
|
||||
end
|
||||
create Result
|
||||
Result.set (y, mon, d, h, m, s)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
seconds_between (a_other: like Current): INTEGER
|
||||
-- The number of seconds between Current and `a_other'.
|
||||
do
|
||||
Result := days_between (a_other) * 24 * 60 * 60 + Precursor {HMS_TIME} (a_other)
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
i: INTEGER
|
||||
ds, ts: STRING
|
||||
do
|
||||
if a_string /= Void then
|
||||
i := a_string.index_of ('T', 1)
|
||||
ds := a_string.substring (1, i - 1)
|
||||
ts := a_string.substring (i + 1, a_string.count)
|
||||
Result := Precursor {YMD_TIME} (ds) and then Precursor {HMS_TIME} (ts)
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
do
|
||||
Result := Precursor {HMS_TIME} (a_integer) and then
|
||||
Precursor {YMD_TIME} (a_integer)
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this date_and_time come before 'other'
|
||||
do
|
||||
Result := year < other.year or else
|
||||
((year = other.year) and (month < other.month)) or else
|
||||
((year = other.year) and (month = other.month) and (day < other.day)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour < other.hour)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute < other.minute)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute = other.minute) and (second < other.second)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute = other.minute) and (second = other.second) and
|
||||
(millisecond < other.millisecond))
|
||||
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is the date and time logical?
|
||||
do
|
||||
Result := Precursor {YMD_TIME} and Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: YMDHMS_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
77
jj_temporal/classes/ymdhms_timer.e
Normal file
77
jj_temporal/classes/ymdhms_timer.e
Normal file
@ -0,0 +1,77 @@
|
||||
note
|
||||
description: "Summary description for {YMDHMS_TIMER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
YMDHMS_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
YMDHMS_INTERVAL
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
HMS_TIMER
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
YMD_TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {YMDHMS_INTERVAL}
|
||||
Precursor {YMD_TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
88
jj_temporal/demo/jj_temporal_demo.e
Normal file
88
jj_temporal/demo/jj_temporal_demo.e
Normal file
@ -0,0 +1,88 @@
|
||||
note
|
||||
description: "[
|
||||
Test objects for temporal cluster.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL: $"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
|
||||
class
|
||||
JJ_TEMPORAL_DEMO
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create date
|
||||
create time
|
||||
create date_time
|
||||
io.put_string (date.out)
|
||||
io.new_line
|
||||
io.new_line
|
||||
io.put_string (time.out)
|
||||
io.new_line
|
||||
io.new_line
|
||||
io.put_string (date_time.out)
|
||||
|
||||
create ymd_formatter
|
||||
create timer_1
|
||||
create timer_2
|
||||
timer_1.reset
|
||||
timer_2.reset
|
||||
|
||||
from i := 1
|
||||
until i > 10
|
||||
loop
|
||||
io.put_string ("i = " + i.out + "%N")
|
||||
timer_1.run
|
||||
ee.sleep (100)
|
||||
timer_1.stop
|
||||
timer_2.run
|
||||
ee.sleep (1_000_000_000)
|
||||
timer_2.stop
|
||||
io.put_string ("timer_1.cumulative = " + timer_1.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
io.put_string ("timer_2.cumulative = " + timer_2.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
i := i + 1
|
||||
end
|
||||
io.put_string ("timer_1.cumulative = " + timer_1.cumulative.as_seconds.out)
|
||||
io.put_string (" %T")
|
||||
io.put_string ("timer_2.cumulative = " + timer_2.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
|
||||
-- io.put_string ("The formatted date = ")
|
||||
-- io.put_string (ymd_formatter.to_string (date) + "%N")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
date: YMD_TIME
|
||||
-- To test a date
|
||||
|
||||
time: HMS_TIME
|
||||
-- To test a time
|
||||
|
||||
date_time: YMDHMS_TIME
|
||||
-- To test a date and time
|
||||
|
||||
ymd_formatter: YMD_TIME_FORMATTER
|
||||
-- To test the gobo parsers
|
||||
|
||||
timer_1, timer_2: HMS_TIMER
|
||||
|
||||
ee: EXECUTION_ENVIRONMENT
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
end
|
23
jj_temporal/demo/jj_temporal_demo.ecf
Normal file
23
jj_temporal/demo/jj_temporal_demo.ecf
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="jj_temporal_demo" uuid="E55510BE-486F-4ED3-A6C5-1FCCECA93777">
|
||||
<target name="jj_temporal_demo">
|
||||
<root class="JJ_TEMPORAL_DEMO" feature="make"/>
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="jj_temporal" location="..\jj_temporal.ecf" readonly="false">
|
||||
<option is_obsolete_routine_type="true">
|
||||
<assertions precondition="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<cluster name="demo" location=".\">
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
18
jj_temporal/docs/Forum.txt
Normal file
18
jj_temporal/docs/Forum.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Eiffel Forum License, version 2
|
||||
|
||||
1. Permission is hereby granted to use, copy, modify and/or
|
||||
distribute this package, provided that:
|
||||
* copyright notices are retained unchanged,
|
||||
* any distribution of this package, whether modified or not,
|
||||
includes this license text.
|
||||
2. Permission is hereby also granted to distribute binary programs
|
||||
which depend on this package. If the binary program depends on a
|
||||
modified version of this package, you are encouraged to publicly
|
||||
release the modified version of this package.
|
||||
|
||||
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THIS PACKAGE.
|
BIN
jj_temporal/docs/main_classes.png
Normal file
BIN
jj_temporal/docs/main_classes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
192
jj_temporal/formatters/hms_duration_formatter.e
Normal file
192
jj_temporal/formatters/hms_duration_formatter.e
Normal file
@ -0,0 +1,192 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {HMS_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_hms_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
date: "18 Feb 03"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (", ")
|
||||
set_hour_minute_second
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_hour_minute_second
|
||||
-- Set format to day-month-year.
|
||||
do
|
||||
format := hms
|
||||
end
|
||||
|
||||
set_second_minute_hour
|
||||
do
|
||||
format := smh
|
||||
end
|
||||
|
||||
set_hour_minute
|
||||
do
|
||||
format := hm
|
||||
end
|
||||
|
||||
set_minute_hour
|
||||
do
|
||||
format := mh
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
hour_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make(8)
|
||||
Result.append_integer (a_duration.hours)
|
||||
Result.append (" hour")
|
||||
if a_duration.hours /= 1 and a_duration.hours /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
minute_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.minutes)
|
||||
Result.append (" minute")
|
||||
if a_duration.minutes /= 1 and a_duration.minutes /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
second_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.seconds)
|
||||
Result.append (" second")
|
||||
if a_duration.seconds /= 1 and a_duration.seconds /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_duration: HMS_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (hour_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (minute_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (second_string(a_duration))
|
||||
end
|
||||
|
||||
string_to_duration (a_string: STRING): HMS_DURATION
|
||||
-- Parse the string based on the current formatting.
|
||||
require
|
||||
valid_date_string: is_valid_duration_string (a_string)
|
||||
do
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_duration_string (a_string: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
-- parse the string
|
||||
Result := True
|
||||
-- !!! temporary
|
||||
end
|
||||
|
||||
is_index_in_hour_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
date_exists: a_date /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ds := hour_string (a_date)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_minute_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ms := minute_string (a_date)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_second_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ys := second_string (a_date)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
format: INTEGER
|
||||
|
||||
hms, smh, -- hours-minutes-seconds, etc
|
||||
hm, mh : INTEGER = unique -- hours-minutes only
|
||||
|
||||
hms_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end -- class HMS_DURATION_FORMATTER
|
||||
|
||||
|
245
jj_temporal/formatters/hms_time_formatter.e
Normal file
245
jj_temporal/formatters/hms_time_formatter.e
Normal file
@ -0,0 +1,245 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {HMS_TIME}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `to_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_hms_time' is more
|
||||
relaxed.
|
||||
]"
|
||||
date: "18 Feb 03"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (":")
|
||||
hide_seconds
|
||||
set_12_hour
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
separator_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_12_hour
|
||||
do
|
||||
is_12_hour := True
|
||||
end
|
||||
|
||||
set_24_hour
|
||||
do
|
||||
is_12_hour := False
|
||||
end
|
||||
|
||||
show_seconds
|
||||
do
|
||||
is_seconds_shown := True
|
||||
end
|
||||
|
||||
hide_seconds
|
||||
do
|
||||
is_seconds_shown := False
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
hour_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
local
|
||||
h: INTEGER
|
||||
do
|
||||
h := a_time.hour
|
||||
if is_12_hour and then h >= 12 then
|
||||
h := h - 12
|
||||
end
|
||||
if is_12_hour and then h = 0 then
|
||||
h := 12
|
||||
end
|
||||
create Result.make(2)
|
||||
if h < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (h)
|
||||
end
|
||||
|
||||
minute_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make(2)
|
||||
if a_time.minute < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_time.minute)
|
||||
end
|
||||
|
||||
second_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make(2)
|
||||
if a_time.second < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_time.second)
|
||||
end
|
||||
|
||||
am_pm_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make (3)
|
||||
if a_time.hour >= 12 then
|
||||
Result.append (" PM")
|
||||
else
|
||||
Result.append (" AM")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_time: like time_anchor): STRING
|
||||
-- the whole {HMS_TIME} as a string
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (hour_string (a_time))
|
||||
Result.append (separator)
|
||||
Result.append (minute_string (a_time))
|
||||
if is_seconds_shown then
|
||||
Result.append (separator)
|
||||
Result.append (second_string (a_time))
|
||||
end
|
||||
if is_12_hour then
|
||||
Result.append (am_pm_string (a_time))
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_12_hour: BOOLEAN
|
||||
|
||||
is_seconds_shown: BOOLEAN
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_time_string (a_time: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_time /= Void
|
||||
do
|
||||
-- parse the string
|
||||
end
|
||||
|
||||
is_index_in_hour_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, hs: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
hs := hour_string (a_time)
|
||||
i := s.substring_index (hs, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + hs.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_minute_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ms := minute_string (a_time)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_second_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ss: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ss := hour_string (a_time)
|
||||
i := s.substring_index (ss, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ss.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_am_pm_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ss: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ss := am_pm_string (a_time)
|
||||
i := s.substring_index (ss, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ss.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
hms_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
192
jj_temporal/formatters/ymd_duration_formatter.e
Normal file
192
jj_temporal/formatters/ymd_duration_formatter.e
Normal file
@ -0,0 +1,192 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMD_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_ymd_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (", ")
|
||||
set_year_month_day
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_day_month_year
|
||||
-- Set format to day-month-year.
|
||||
do
|
||||
format := dmy
|
||||
end
|
||||
|
||||
set_year_month_day
|
||||
do
|
||||
format := ymd
|
||||
end
|
||||
|
||||
set_day_month
|
||||
do
|
||||
format := dm
|
||||
end
|
||||
|
||||
set_month_year
|
||||
do
|
||||
format := my
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
year_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make(8)
|
||||
Result.append_integer (a_duration.years)
|
||||
Result.append (" year")
|
||||
if a_duration.years /= 1 and a_duration.years /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
month_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.months)
|
||||
Result.append (" month")
|
||||
if a_duration.months /= 1 and a_duration.months /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
day_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.days)
|
||||
Result.append (" day")
|
||||
if a_duration.days /= 1 and a_duration.days /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_duration: YMD_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (day_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (month_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (year_string(a_duration))
|
||||
end
|
||||
|
||||
string_to_duration (a_string: STRING): YMD_DURATION
|
||||
-- Parse the string based on the current formatting.
|
||||
require
|
||||
valid_date_string: is_valid_date_string (a_string)
|
||||
do
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_date_string (a_string: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
-- parse the string
|
||||
Result := True
|
||||
-- !!! temporary
|
||||
end
|
||||
|
||||
is_index_in_day_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
date_exists: a_date /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ds := day_string (a_date)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_month_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ms := month_string (a_date)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_year_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ys := year_string (a_date)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
format: INTEGER
|
||||
|
||||
dmy, ymd, -- day-month-year, etc
|
||||
dm, my : INTEGER = unique -- day-month or month-year only
|
||||
|
||||
dmy_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end -- class YMD_DURATION_FORMATTER
|
||||
|
||||
|
133
jj_temporal/formatters/ymd_time_format_constants.e
Normal file
133
jj_temporal/formatters/ymd_time_format_constants.e
Normal file
@ -0,0 +1,133 @@
|
||||
note
|
||||
description: "[
|
||||
Constants describing how {YMD_TIME}'s (dates) should appear.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
|
||||
feature -- Assess
|
||||
|
||||
Day_month_year: INTEGER = 0
|
||||
-- (e.g. "31 January 2004" or "31/01/04")
|
||||
|
||||
Year_month_day: INTEGER = 1
|
||||
-- (e.g. "2004 January 31" or "04/01/31")
|
||||
|
||||
Month_day_year: INTEGER = 2
|
||||
-- (e.g. "January 31, 2004" or "01/31/04")
|
||||
|
||||
Day_month: INTEGER = 3
|
||||
-- (e.g. "31 January" or "31/01")
|
||||
|
||||
Month_year: INTEGER = 4
|
||||
-- (e.g. "January 2004" or "01/04")
|
||||
|
||||
days_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("SUN")
|
||||
Result.extend ("MON")
|
||||
Result.extend ("TUE")
|
||||
Result.extend ("WED")
|
||||
Result.extend ("THU")
|
||||
Result.extend ("FRI")
|
||||
Result.extend ("SAT")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
months_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("JAN")
|
||||
Result.extend ("FEB")
|
||||
Result.extend ("MAR")
|
||||
Result.extend ("APR")
|
||||
Result.extend ("MAY")
|
||||
Result.extend ("JUN")
|
||||
Result.extend ("JUL")
|
||||
Result.extend ("AUG")
|
||||
Result.extend ("SEP")
|
||||
Result.extend ("OCT")
|
||||
Result.extend ("NOV")
|
||||
Result.extend ("DEC")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
long_days_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("SUNDAY")
|
||||
Result.extend ("MONDAY")
|
||||
Result.extend ("TUESDAY")
|
||||
Result.extend ("WEDNESDAY")
|
||||
Result.extend ("THURSDAY")
|
||||
Result.extend ("FRIDAY")
|
||||
Result.extend ("SATURDAY")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
long_months_text: LINKED_LIST [STRING]
|
||||
--
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("JANUARY")
|
||||
Result.extend ("FEBRUARY")
|
||||
Result.extend ("MARCH")
|
||||
Result.extend ("APRIL")
|
||||
Result.extend ("MAY")
|
||||
Result.extend ("JUNE")
|
||||
Result.extend ("JULY")
|
||||
Result.extend ("AUGUST")
|
||||
Result.extend ("SEPTEMBER")
|
||||
Result.extend ("OCTOBER")
|
||||
Result.extend ("NOVEMBER")
|
||||
Result.extend ("DECEMBER")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_valid_format (a_integer: INTEGER): BOOLEAN
|
||||
-- Does `a_integer' represent a valid date format?
|
||||
do
|
||||
Result := a_integer = Day_month_year or else
|
||||
a_integer = Year_month_day or else
|
||||
a_integer = Month_day_year or else
|
||||
a_integer = Day_month or else
|
||||
a_integer = Month_year
|
||||
end
|
||||
|
||||
is_month (a_string: STRING): BOOLEAN
|
||||
-- Does a_string represent a month?
|
||||
do
|
||||
Result := months_text.has (a_string.as_upper) or else
|
||||
long_months_text.has (a_string.as_upper)
|
||||
end
|
||||
|
||||
is_weekday (a_string: STRING): BOOLEAN
|
||||
-- Does `a_string' represent a weekday?
|
||||
do
|
||||
Result := days_text.has (a_string.as_upper) or else
|
||||
long_days_text.has (a_string.as_upper)
|
||||
end
|
||||
|
||||
get_month (a_month: STRING): INTEGER
|
||||
-- Number of the `a_month'
|
||||
require
|
||||
is_month: is_month (a_month)
|
||||
do
|
||||
if months_text.has (a_month.as_upper) then
|
||||
Result := months_text.index_of (a_month.as_upper, 1)
|
||||
else
|
||||
Result := long_months_text.index_of (a_month.as_upper, 1)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
397
jj_temporal/formatters/ymd_time_formatter.e
Normal file
397
jj_temporal/formatters/ymd_time_formatter.e
Normal file
@ -0,0 +1,397 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMD_TIME}'s (i.e. dates) to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymd_time' is more relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance to parse dates in "dd mmm yy" format.
|
||||
do
|
||||
set_separator (" ")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
-- The character (or string) placed between the day, month, year, etc.
|
||||
|
||||
to_ymd_time (a_string: STRING): like time_anchor
|
||||
-- Parse `a_string'
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
is_string_valid: is_valid (a_string)
|
||||
do
|
||||
Result := parsed (a_string)
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
to_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The complete string representation of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (20)
|
||||
inspect format
|
||||
when Day_month_year then
|
||||
if is_weekday_included then
|
||||
Result.append (weekday_string (a_ymd_time))
|
||||
Result.append (", ")
|
||||
end
|
||||
Result.append (day_string (a_ymd_time))
|
||||
Result.append (separator)
|
||||
Result.append (month_string (a_ymd_time))
|
||||
Result.append (separator)
|
||||
Result.append (year_string (a_ymd_time))
|
||||
when Year_month_day then
|
||||
when Month_day_year then
|
||||
when Month_year then
|
||||
when Day_month then
|
||||
else
|
||||
check
|
||||
should_not_happen: False
|
||||
-- because format must be one of these
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
year_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `year' feature of `a_ymd_time'.
|
||||
-- Will be shortened to two characters if `is_short_format'.
|
||||
do
|
||||
create Result.make(4)
|
||||
Result.append_integer (a_ymd_time.year)
|
||||
if is_short_format then
|
||||
if a_ymd_time.year < 10 then
|
||||
Result.keep_tail (1)
|
||||
if is_zero_padded then
|
||||
Result.prepend ("0")
|
||||
end
|
||||
else
|
||||
Result.keep_tail (2)
|
||||
end
|
||||
else
|
||||
if is_zero_padded then
|
||||
if a_ymd_time.year < 10 then
|
||||
Result.prepend ("000")
|
||||
elseif a_ymd_time.year < 100 then
|
||||
Result.prepend ("00")
|
||||
elseif a_ymd_time.year < 1000 then
|
||||
Result.prepend ("0")
|
||||
end
|
||||
end
|
||||
end
|
||||
ensure
|
||||
valid_length_if_short: is_short_format implies Result.count <= 2
|
||||
end
|
||||
|
||||
month_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `month' feature of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (10)
|
||||
if is_month_numeric then
|
||||
if is_zero_padded and a_ymd_time.month < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_ymd_time.month)
|
||||
else
|
||||
if is_short_format then
|
||||
Result.append (months_text.i_th (a_ymd_time.month))
|
||||
else
|
||||
Result.append (long_months_text.i_th (a_ymd_time.month))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
day_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `day' feature of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (2)
|
||||
if is_zero_padded and a_ymd_time.day < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_ymd_time.day)
|
||||
end
|
||||
|
||||
weekday_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string repesentation of the `weekday' of `a_ymd_time'.
|
||||
-- (i.e. "Sunday", "Monday, etc. or "Sun", "Mon", etc.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (15)
|
||||
inspect a_ymd_time.weekday
|
||||
when 1 then Result.append ("Sunday")
|
||||
when 2 then Result.append ("Monday")
|
||||
when 3 then Result.append ("Tuesday")
|
||||
when 4 then Result.append ("Wednesday")
|
||||
when 5 then Result.append ("Thursday")
|
||||
when 6 then Result.append ("Friday")
|
||||
when 7 then Result.append ("Saturday")
|
||||
else
|
||||
check
|
||||
should_not_happen: False
|
||||
-- because `weekday' ranges from 1 to 7.
|
||||
end
|
||||
end
|
||||
if is_short_format then
|
||||
Result.keep_head (3)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
-- Set `separator' to `a_string'.
|
||||
require
|
||||
separator_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
ensure
|
||||
seperator_set: separator = a_string
|
||||
end
|
||||
|
||||
set_format (a_format: INTEGER)
|
||||
-- Change `format'.
|
||||
-- The values are in YMD_TIME_FORMAT_CONSTANTS
|
||||
require
|
||||
valid_format: is_valid_format (a_format)
|
||||
do
|
||||
format := a_format
|
||||
end
|
||||
|
||||
set_show_weekday
|
||||
-- Include the day of the week in the output string.
|
||||
do
|
||||
is_weekday_included := True
|
||||
end
|
||||
|
||||
set_hide_weekday
|
||||
-- Do not include the day of the week in the output string.
|
||||
do
|
||||
is_weekday_included := False
|
||||
end
|
||||
|
||||
set_format_short
|
||||
-- Abriviate the `month_string' (if shown as text) to three
|
||||
-- characters and shorten the year to two digits.
|
||||
do
|
||||
is_short_format := True
|
||||
end
|
||||
|
||||
set_format_long
|
||||
-- Show the `month_string' (if shown as text) to the complete
|
||||
-- (unabriviated) word and show the year as four digits.
|
||||
do
|
||||
is_short_format := False
|
||||
end
|
||||
|
||||
set_month_numeric
|
||||
-- Make the month appear as digits, not text.
|
||||
do
|
||||
is_month_numeric := True
|
||||
ensure
|
||||
showing_month_as_digits: is_month_numeric
|
||||
end
|
||||
|
||||
set_month_text
|
||||
-- Make the month appear as text.
|
||||
-- It may be full text or abbriviated depending on `is_format_short'.
|
||||
do
|
||||
is_month_numeric := False
|
||||
ensure
|
||||
showing_month_as_text: not is_month_numeric
|
||||
end
|
||||
|
||||
set_pad_zeros
|
||||
-- Make sure the `day_string', `year_string', and `month_string' (when
|
||||
-- `is_month_numeric') are padded with leading zeros when necessary.
|
||||
-- For example, in numeric form "9 Jan 2004" may be shown as "09/01/04".
|
||||
do
|
||||
is_zero_padded := True
|
||||
ensure
|
||||
zero_padding_set: is_zero_padded
|
||||
end
|
||||
|
||||
set_hide_zeros
|
||||
-- Do not pad numeric values with leading zeros.
|
||||
do
|
||||
is_zero_padded := False
|
||||
ensure
|
||||
not_padded: not is_zero_padded
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
save_format
|
||||
-- Save the `format' for restoration later.
|
||||
do
|
||||
saved := format
|
||||
ensure
|
||||
format_saved: saved = format
|
||||
end
|
||||
|
||||
restore_format
|
||||
-- Reset `format' to the value `saved' by a call to `save_format'.
|
||||
do
|
||||
format := saved
|
||||
ensure
|
||||
format_restored: format = saved
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' convertable to a date?
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
Result := parsed (a_string) /= Void
|
||||
ensure
|
||||
definition: Result implies parsed (a_string) /= Void
|
||||
end
|
||||
|
||||
is_weekday_included: BOOLEAN
|
||||
-- Is the day of week (ie "Monday") in ymd_time string.
|
||||
|
||||
is_short_format: BOOLEAN
|
||||
-- Is the year two digits instead of four and
|
||||
-- is the month abriviated?
|
||||
|
||||
is_month_numeric: BOOLEAN
|
||||
-- Is the `month_string' shown as digits? (As opposed to a
|
||||
-- textual representation such as "January".)
|
||||
|
||||
is_zero_padded: BOOLEAN
|
||||
-- Are digital values to be padded with leading zero's if
|
||||
-- shorter than normal?
|
||||
|
||||
is_index_in_day_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ds := day_string (a_ymd_time)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_month_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ms := month_string (a_ymd_time)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_year_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ys := year_string (a_ymd_time)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_weekday_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, wds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
wds := weekday_string (a_ymd_time)
|
||||
i := s.substring_index (wds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + wds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
parsed (a_string: STRING): like time_anchor
|
||||
-- Attemp to convert `a_string' to a {YMD_TIME}, returning
|
||||
-- Void if unable.
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
string_has_length: a_string.count >= 1
|
||||
local
|
||||
p: YMD_TIME_PARSER
|
||||
do
|
||||
create p
|
||||
-- p.set_format (format)
|
||||
-- p.parse_string (a_string)
|
||||
-- Result := p.last_value
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
format: INTEGER
|
||||
|
||||
saved: INTEGER
|
||||
-- used to save the format.
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
valid_ymd_time_format: is_valid_format (format)
|
||||
|
||||
end
|
||||
|
||||
|
68
jj_temporal/formatters/ymdhms_duration_formatter.e
Normal file
68
jj_temporal/formatters/ymdhms_duration_formatter.e
Normal file
@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMDHMS_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymdhms_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_DURATION_FORMATTER
|
||||
rename
|
||||
to_string as time_string,
|
||||
set_separator as set_time_separator,
|
||||
separator as time_separator,
|
||||
string_to_duration as hms_string_to_duration,
|
||||
format as hms_format
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_DURATION_FORMATTER
|
||||
rename
|
||||
to_string as date_string,
|
||||
set_separator as set_date_separator,
|
||||
separator as date_separator,
|
||||
string_to_duration as ymd_string_to_duration,
|
||||
format as ymd_format
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
--
|
||||
do
|
||||
Precursor {HMS_DURATION_FORMATTER}
|
||||
Precursor {YMD_DURATION_FORMATTER}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
to_string (a_duration: YMDHMS_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
create Result.make (30)
|
||||
Result.append (date_string (a_duration))
|
||||
Result.append (" ")
|
||||
Result.append (time_string (a_duration))
|
||||
end
|
||||
|
||||
end -- class YMDHMS_DURATION_FORMATTER
|
126
jj_temporal/formatters/ymdhms_time_formatter.e
Normal file
126
jj_temporal/formatters/ymdhms_time_formatter.e
Normal file
@ -0,0 +1,126 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMDHMS_TIME}'s (i.e. date/times) to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymd_time' is more relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_TIME_FORMATTER
|
||||
rename
|
||||
set_separator as set_time_separator,
|
||||
separator as time_separator
|
||||
redefine
|
||||
default_create,
|
||||
to_string,
|
||||
time_anchor
|
||||
end
|
||||
|
||||
YMD_TIME_FORMATTER
|
||||
rename
|
||||
set_separator as set_date_separator,
|
||||
separator as date_separator
|
||||
redefine
|
||||
default_create,
|
||||
to_string,
|
||||
time_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
Precursor {HMS_TIME_FORMATTER}
|
||||
Precursor {YMD_TIME_FORMATTER}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
to_string (a_time: like time_anchor): STRING
|
||||
-- the whole date as a string
|
||||
do
|
||||
create Result.make (30)
|
||||
if not is_date_hidden then
|
||||
Result.append (Precursor {YMD_TIME_FORMATTER} (a_time))
|
||||
Result.append (" ")
|
||||
end
|
||||
if not is_time_hidden then
|
||||
Result.append (Precursor {HMS_TIME_FORMATTER} (a_time))
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_time_hidden: BOOLEAN
|
||||
-- Will `to_string' not include the time?
|
||||
|
||||
is_date_hidden: BOOLEAN
|
||||
-- Will `to_string' not include the date?
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
hide_time
|
||||
-- Make `to_string' produce a string showing the date only;
|
||||
-- the time portion will not show.
|
||||
do
|
||||
is_time_hidden := True
|
||||
is_date_hidden := False
|
||||
ensure
|
||||
time_is_hidden: is_time_hidden
|
||||
date_is_shown: not is_date_hidden
|
||||
end
|
||||
|
||||
hide_date
|
||||
-- Make `a_string' produce a string showing the time only;
|
||||
-- the date portionn will not show.
|
||||
do
|
||||
is_date_hidden := True
|
||||
is_time_hidden := False
|
||||
ensure
|
||||
date_is_hidden: is_date_hidden
|
||||
time_is_shown: not is_time_hidden
|
||||
end
|
||||
|
||||
show_date_and_time
|
||||
-- Make `to_string' produce a string showing both the date
|
||||
-- portion and the time portion. This is the default.
|
||||
do
|
||||
is_date_hidden := False
|
||||
is_time_hidden := False
|
||||
ensure
|
||||
date_is_shown: not is_date_hidden
|
||||
time_is_shown: not is_time_hidden
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
not_both_date_and_time_hidden: not (is_date_hidden and is_time_hidden)
|
||||
|
||||
end
|
7
jj_temporal/jj_t/README.md
Normal file
7
jj_temporal/jj_t/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# jj_temporal
|
||||
Eiffel date and time classes
|
||||
|
||||
Main classes: ![](docs/main_classes.png?raw=true)
|
||||
|
||||
|
||||
|
229
jj_temporal/jj_t/classes/abstract_duration.e
Normal file
229
jj_temporal/jj_t/classes/abstract_duration.e
Normal file
@ -0,0 +1,229 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a duration of time such as 2 hours, or 3 years, etc.
|
||||
]"
|
||||
names: "abstract_duration, duration"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_DURATION
|
||||
|
||||
inherit
|
||||
COMPARABLE
|
||||
|
||||
feature -- Access
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string, ideally with not extra characters.
|
||||
deferred
|
||||
end
|
||||
|
||||
negative: like Current
|
||||
-- The negative value of this duration
|
||||
do
|
||||
Result := twin
|
||||
Result.negate
|
||||
ensure
|
||||
negative_result: Current > zero implies Result < zero
|
||||
positive_result: Current < zero implies Result > zero
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
deferred
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
valid_result: Result.is_one
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
deferred
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
good_result: Result.is_zero
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_zero: BOOLEAN
|
||||
-- Is this duration of 0 length?
|
||||
do
|
||||
Result := equal (Current, zero)
|
||||
ensure
|
||||
valid_result: Result implies equal (Current, zero)
|
||||
end
|
||||
|
||||
is_one: BOOLEAN
|
||||
-- Is this duration neutral for '*' and '/'?
|
||||
do
|
||||
Result := equal (Current, one)
|
||||
ensure
|
||||
valid_result: Result implies equal (Current, one)
|
||||
end
|
||||
|
||||
is_negative: BOOLEAN
|
||||
-- Is current less than the 'zero' duration?
|
||||
do
|
||||
Result := Current < zero
|
||||
ensure
|
||||
valid_result: Result implies Current < zero
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_zero
|
||||
-- Make the duration have zero length.
|
||||
deferred
|
||||
ensure
|
||||
is_zero: is_zero
|
||||
end
|
||||
|
||||
|
||||
negate
|
||||
-- Reverses the sign.
|
||||
deferred
|
||||
ensure
|
||||
positive_implication: not is_negative implies old is_negative
|
||||
negative_implication: is_negative implies not old is_negative
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other other to Current.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from Current
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
deferred
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
require
|
||||
not_zero_devisor: r /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
deferred
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
-- For example: is current duration at least twice as long as other?
|
||||
require
|
||||
other_exists: other /= Void
|
||||
other_not_zero: not other.is_zero
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
identity alias "+": like Current
|
||||
-- Just a clone of Current. Included for symetry.
|
||||
do
|
||||
Result := twin
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
oposite alias "-": like Current
|
||||
-- Invert the sign of other.
|
||||
do
|
||||
Result := twin
|
||||
Result.negate
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
plus alias "+" (other: like Current): like Current
|
||||
-- Sum of current and other.
|
||||
do
|
||||
Result := twin
|
||||
Result.add (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
minus alias "-" (other: like Current): like Current
|
||||
-- Difference of Current and other.
|
||||
do
|
||||
Result := twin
|
||||
Result.sub (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
product alias "*" (r: DOUBLE): like Current
|
||||
-- Product of Current and 'r'.
|
||||
-- Multiply by a factor of 'r'.
|
||||
do
|
||||
Result := twin
|
||||
Result.multiply (r)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
quotient alias "/" (r: DOUBLE): like Current
|
||||
-- Quotent of Current by 'r'.
|
||||
require
|
||||
not_zero_devisor: r /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.divide (r)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
integer_quotient alias "//" (i: INTEGER): like Current
|
||||
-- Integer division of Current by 'i'.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.div (i)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
integer_remainder alias "\\" (i: INTEGER): like Current
|
||||
-- Modulo of Current by 'i'.
|
||||
require
|
||||
not_zero_devisor: i /= 0
|
||||
do
|
||||
Result := twin
|
||||
Result.mod (i)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
end
|
||||
|
387
jj_temporal/jj_t/classes/abstract_interval.e
Normal file
387
jj_temporal/jj_t/classes/abstract_interval.e
Normal file
@ -0,0 +1,387 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a span of time consisting of a start-time, a
|
||||
finish-time and a duration. Positive durations only.
|
||||
]"
|
||||
names: "abstract_interval, time_span, time_interval, span"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
COMPARABLE
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
start: like time_anchor
|
||||
-- Beginning moment of the time span and anchor for class.
|
||||
do
|
||||
Result := start_imp.twin
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
finish: like time_anchor
|
||||
-- Ending moment of the time span.
|
||||
do
|
||||
Result := finish_imp.twin
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
duration: like duration_anchor
|
||||
-- Length of time span.
|
||||
do
|
||||
Result := finish.time_between (start)
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_start_finish (a_start_time, a_finish_time: like time_anchor)
|
||||
-- Set the `start' and `finish' times.
|
||||
require
|
||||
times_exists: a_start_time /= Void and a_finish_time /= Void
|
||||
valid_times: a_start_time <= a_finish_time
|
||||
do
|
||||
start_imp := a_start_time.twin
|
||||
finish_imp := a_finish_time.twin
|
||||
ensure
|
||||
start_was_set: equal (start, a_start_time)
|
||||
finish_was_set: equal (finish, a_finish_time)
|
||||
end
|
||||
|
||||
set_start_duration (a_start_time: like time_anchor; a_duration: like duration_anchor)
|
||||
-- Set the `start' time and the `duration'.
|
||||
require
|
||||
start_time_exists: a_start_time /= Void
|
||||
duration_exists: a_duration /= Void
|
||||
positive_duration: not a_duration.is_negative
|
||||
do
|
||||
start_imp := a_start_time.twin
|
||||
finish_imp := a_start_time + a_duration
|
||||
ensure
|
||||
start_was_set: equal (start, a_start_time)
|
||||
duration_was_set: equal (duration, a_duration)
|
||||
end
|
||||
|
||||
set_duration_finish (a_duration: like duration_anchor; a_finish_time: like time_anchor)
|
||||
-- Set the `duration' and `finish' time.
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
positive_duration: not a_duration.is_negative
|
||||
finish_time_exists: a_finish_time /= Void
|
||||
do
|
||||
start_imp := a_finish_time - a_duration
|
||||
finish_imp := a_finish_time.twin
|
||||
ensure
|
||||
finish_was_set: equal (finish, a_finish_time)
|
||||
duration_was_set: equal (duration, a_duration)
|
||||
end
|
||||
|
||||
move (a_duration: like duration_anchor)
|
||||
-- Change the `start' and `finish' times by moving the
|
||||
-- interval by the amount represented by `a_duration'.
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
start_imp.add_duration (a_duration)
|
||||
finish_imp.add_duration (a_duration)
|
||||
ensure
|
||||
duration_unchanged: equal (duration, old duration)
|
||||
end
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does current interval start before other or if they start at the
|
||||
-- same time, does Current end before the other?
|
||||
do
|
||||
if (start < other.start) or else
|
||||
(start.is_equal (other.start) and then finish < other.finish) then
|
||||
Result := true
|
||||
end
|
||||
ensure then
|
||||
less_than_definition: Result implies (start < other.start or else
|
||||
(start.is_equal (other.start) and then finish < other.finish))
|
||||
end
|
||||
|
||||
meets (other: like Current): BOOLEAN
|
||||
-- x.meets(y) |-----x----->|
|
||||
-- y.is_met_by(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := equal (finish, other.start)
|
||||
ensure
|
||||
Result implies equal (finish, other.start)
|
||||
Result implies Current < other
|
||||
end
|
||||
|
||||
is_met_by (other: like Current): BOOLEAN
|
||||
-- x.meets(y) |-----x----->|
|
||||
-- y.is_met_by(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := equal (start, other.finish)
|
||||
ensure
|
||||
Result implies equal (start, other.finish)
|
||||
Result implies other < Current
|
||||
end
|
||||
|
||||
is_before (other: like Current): BOOLEAN
|
||||
-- x.is_before(y) |-----x----->|
|
||||
-- y.is_after(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := finish < other.start
|
||||
ensure
|
||||
Result implies finish.is_before (other)
|
||||
Result implies Current < other
|
||||
end
|
||||
|
||||
is_after (other: like Current): BOOLEAN
|
||||
-- x.is_before(y) |-----x----->|
|
||||
-- y.is_after(x) |-----y----->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := start > other.finish
|
||||
ensure
|
||||
Result implies start.is_after (other)
|
||||
Result implies other < Current
|
||||
end
|
||||
|
||||
includes (other: like Current): BOOLEAN
|
||||
-- x.includes(y) |-----x----->|
|
||||
-- y.is_included_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := other.start.belongs (Current) and
|
||||
other.finish.belongs (Current)
|
||||
ensure
|
||||
Result implies other.start.belongs (Current);
|
||||
Result implies other.finish.belongs (Current)
|
||||
end
|
||||
|
||||
is_included_by (other: like Current): BOOLEAN
|
||||
-- x.includes(y) |-----x----->|
|
||||
-- y.is_included_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := start.belongs (other) and finish.belongs (other)
|
||||
ensure
|
||||
Result implies start.belongs (other);
|
||||
Result implies finish.belongs (other);
|
||||
end
|
||||
|
||||
overlaps (other: like Current): BOOLEAN
|
||||
-- x.overlaps(y) |-----x----->|
|
||||
-- y.is_overlapped_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := finish.belongs (other)
|
||||
ensure
|
||||
Result implies finish.belongs (other)
|
||||
end
|
||||
|
||||
is_overlapped_by (other: like Current): BOOLEAN
|
||||
-- x.overlaps(y) |-----x----->|
|
||||
-- y.is_overlapped_by(x) |--y-->|
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := other.finish.belongs (Current)
|
||||
ensure
|
||||
Result implies other.finish.belongs (Current)
|
||||
end
|
||||
|
||||
intersects (other: like Current): BOOLEAN
|
||||
-- Do the two intervals have a least one time point in common?
|
||||
require
|
||||
other_exists: other /= Void
|
||||
do
|
||||
Result := meets (other) or is_met_by (other) or else
|
||||
includes (other) or is_included_by (other) or else
|
||||
overlaps (other) or is_overlapped_by (other)
|
||||
ensure
|
||||
Result implies meets (other) or is_met_by (other) or else
|
||||
includes (other) or is_included_by (other) or else
|
||||
overlaps (other) or is_overlapped_by (other)
|
||||
end
|
||||
|
||||
feature -- Transformation
|
||||
|
||||
unite (other: like Current)
|
||||
-- Transform into the union between this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |------------x.union(y)----------->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
local
|
||||
temp_start: like time_anchor
|
||||
temp_finish: like finish
|
||||
do
|
||||
temp_start := start.min (other.start)
|
||||
temp_finish := finish.max (other.finish)
|
||||
set_start_finish (temp_start, temp_finish);
|
||||
ensure
|
||||
valid_result: equal (start, old start.min(other.start)) and
|
||||
equal (finish, old finish.max(other.finish))
|
||||
end
|
||||
|
||||
intersect (other: like Current)
|
||||
-- Transform into the intersection of this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |--x.intersection(y)-->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
local
|
||||
temp_start: like time_anchor
|
||||
temp_finish: like finish
|
||||
do
|
||||
temp_start := start.max (other.start)
|
||||
temp_finish := finish.min (other.finish)
|
||||
set_start_finish (temp_start, temp_finish);
|
||||
ensure
|
||||
valid_result: equal (start, old start.max(other.start)) and
|
||||
equal (finish, old finish.min(other.finish))
|
||||
end
|
||||
|
||||
split (a_time: like time_anchor): like Current
|
||||
-- Transform by splitting the interval at 'a_time'.
|
||||
-- Result is the interval after 'a_time'.
|
||||
-- |
|
||||
-- time
|
||||
-- |
|
||||
-- V
|
||||
-- |-----Current----------------->|
|
||||
-- |---Current--->|----Result---->|
|
||||
-- Only valid if time is within the interval.
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
time_in_interval: a_time.belongs (Current)
|
||||
do
|
||||
Result := twin
|
||||
set_start_finish (start, a_time)
|
||||
Result.set_start_finish (a_time, Result.finish)
|
||||
ensure
|
||||
closure: equal (old Current, Result.union (Current))
|
||||
meets_result: Current.meets (Result)
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
union (other: like Current): like Current
|
||||
-- The union between this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |------------x.union(y)----------->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
do
|
||||
Result := twin
|
||||
Result.unite (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
valid_result: equal (Result.start, start.min(other.start)) and
|
||||
equal (Result.finish, finish.max(other.finish))
|
||||
end
|
||||
|
||||
intersection (other: like Current): like Current
|
||||
-- The intersection of this interval and the other.
|
||||
-- |-------------x------------->|
|
||||
-- |-------------y------------->|
|
||||
-- |--x.intersection(y)-->|
|
||||
-- Only valid if at least one time point common to both.
|
||||
require
|
||||
other_exists: other /= Void
|
||||
intersecting_intervals: intersects (other)
|
||||
do
|
||||
Result := twin
|
||||
Result.intersect (other)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
valid_result: equal (Result.start, start.max (other.start)) and
|
||||
equal (Result.finish, finish.min(other.finish))
|
||||
end
|
||||
|
||||
time_at_percent (a_ratio: DOUBLE): like time_anchor
|
||||
-- Time based on some percentage of this interval.
|
||||
-- Example 1: if 'a_ratio' is 0.0 then result = 'start'; if
|
||||
-- 'a_ratio' is 0.5 then resulting time is 1/2 the distance
|
||||
-- from start to finish; if 'a_ratio' is 2.0 then resulting time
|
||||
-- is at twice the duration from start to finish.
|
||||
do
|
||||
Result := start + (duration * a_ratio)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
start_imp: like time_anchor
|
||||
-- Used internally to prevent changes to `start' which could otherwise
|
||||
-- be induced by calls to a _TIME.
|
||||
|
||||
finish_imp: like time_anchor
|
||||
-- Used internally to prevent changes to `finish' which could otherwise
|
||||
-- be induced by calls to a _TIME.
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: ABSTRACT_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: ABSTRACT_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
is_initialized: start_imp /= Void and finish_imp /= Void
|
||||
start_before_finish: start <= finish
|
||||
positive_duration: not duration.is_negative
|
||||
|
||||
end
|
273
jj_temporal/jj_t/classes/abstract_time.e
Normal file
273
jj_temporal/jj_t/classes/abstract_time.e
Normal file
@ -0,0 +1,273 @@
|
||||
note
|
||||
description: "[
|
||||
Notion of a time, such as <1 Jan 98> or <10:30 P.M.> or <the moment of creation>, etc.
|
||||
]"
|
||||
names: "abstract_time, time, date"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
ABSTRACT_TIME
|
||||
|
||||
inherit
|
||||
COMPARABLE
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string, ideally with not extra characters.
|
||||
deferred
|
||||
end
|
||||
|
||||
as_integer: INTEGER
|
||||
-- The time as represented by an INTEGER.
|
||||
require
|
||||
is_representable: is_representable_as_integer
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
set_now
|
||||
-- Set current time according to timezone.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
deferred
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
require
|
||||
valid_string_representation: is_valid_string_representation (a_string)
|
||||
deferred
|
||||
end
|
||||
|
||||
from_integer (a_integer: INTEGER)
|
||||
-- Change Current to the time represented by `a_integer'.
|
||||
require
|
||||
valid_integer_representation: is_valid_integer_representation (a_integer)
|
||||
deferred
|
||||
end
|
||||
|
||||
add_duration (a_duration: like duration_anchor)
|
||||
-- adds a duration to Current time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
plus alias "+" (a_duration: like duration_anchor): like Current
|
||||
-- same as add_duration except returns a new time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
Result := twin
|
||||
Result.add_duration (a_duration)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
minus alias "-" (a_duration: like duration_anchor): like Current
|
||||
-- same as adding a negative duration except returns a new time
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
Result := twin
|
||||
Result.add_duration (a_duration.negative)
|
||||
ensure
|
||||
no_side_effect: equal (Current, old Current)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_before (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Is this time before the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current < a_interval.start
|
||||
ensure
|
||||
valid_result: Result implies Current < a_interval.start
|
||||
end
|
||||
|
||||
is_after (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Is this time after the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current > a_interval.finish
|
||||
ensure
|
||||
valid_result: Result implies Current > a_interval.finish
|
||||
end
|
||||
|
||||
belongs (a_interval: like interval_anchor): BOOLEAN
|
||||
-- Does this time fall somewhere during the interval?
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
do
|
||||
Result := Current >= a_interval.start and Current <= a_interval.finish
|
||||
ensure
|
||||
valid_result: Result implies Current >= a_interval.start and Current <= a_interval.finish
|
||||
end
|
||||
|
||||
is_between (time_1, time_2: like Current): BOOLEAN
|
||||
-- Is current between the two times?
|
||||
require
|
||||
others_exist: time_1 /= Void and time_2 /= Void
|
||||
do
|
||||
if time_1 < Current and Current < time_2 then
|
||||
Result := True
|
||||
elseif time_2 < Current and Current < time_1 then
|
||||
Result := True
|
||||
end
|
||||
ensure
|
||||
valid_result: Result implies ((time_1 < Current and Current < time_2) or else
|
||||
(time_2 < Current and Current < time_1))
|
||||
end
|
||||
|
||||
is_between_inclusive (time_1, time_2: like Current): BOOLEAN
|
||||
-- Is current between the two times or equal to one of the two times?
|
||||
require
|
||||
others_exist: time_1 /= Void and time_2 /= Void
|
||||
do
|
||||
if time_1 <= Current and Current <= time_2 then
|
||||
Result := True
|
||||
elseif time_2 <= Current and Current <= time_1 then
|
||||
Result := True
|
||||
end
|
||||
ensure
|
||||
valid_result: Result implies ((time_1 <= Current and Current <= time_2) or else
|
||||
(time_2 <= Current and Current <= time_1))
|
||||
end
|
||||
|
||||
percent_of (a_interval: like interval_anchor): DOUBLE
|
||||
-- Where does this time fall in relation to the interval?
|
||||
-- If current time is before the interval then result should be negative.
|
||||
-- If current time is after the interval then result should be > 1 (i.e. > 100%).
|
||||
-- If current time belongs to the interval then result should be between 0 and 1.
|
||||
require
|
||||
interval_exists: a_interval /= Void
|
||||
local
|
||||
int: like Interval_anchor
|
||||
do
|
||||
-- int := twin (a_interval)
|
||||
int := a_interval.deep_twin
|
||||
if is_before (a_interval) then
|
||||
int.set_start_finish (Current, a_interval.start)
|
||||
if not a_interval.duration.is_zero then
|
||||
Result := -(int.duration.percent_of (a_interval.duration))
|
||||
end
|
||||
else
|
||||
int.set_start_finish (a_interval.start, Current)
|
||||
if not a_interval.duration.is_zero then
|
||||
Result := int.duration.percent_of (a_interval.duration)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
negative_if_before: Result < 0 implies Current.is_before (a_interval)
|
||||
zero_to_one_if_belongs: (Result >= 0 and Result <= 1) implies Current.belongs (a_interval)
|
||||
over_one_if_after: Result > 1 implies Current.is_after (a_interval)
|
||||
end
|
||||
|
||||
time_between (other: like Current): like duration_anchor
|
||||
-- The duration of time between Current and other
|
||||
require
|
||||
other_exists: other /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
deferred
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in the range reconizable by Current?
|
||||
deferred
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
C_date: C_DATE
|
||||
-- Used to set the date and time based on system clock.
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Test used by invariant.
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: ABSTRACT_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: ABSTRACT_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
always_valid: is_valid
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2015, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
end
|
||||
|
||||
|
||||
|
255
jj_temporal/jj_t/classes/c_date.e
Normal file
255
jj_temporal/jj_t/classes/c_date.e
Normal file
@ -0,0 +1,255 @@
|
||||
note
|
||||
description: "Representation of a date at C level"
|
||||
legal: "See notice at end of class."
|
||||
status: "See notice at end of class."
|
||||
date: "$Date: 2014-03-11 23:16:07 -0400 (Tue, 11 Mar 2014) $"
|
||||
revision: "$Revision: 35 $"
|
||||
|
||||
class
|
||||
C_DATE
|
||||
|
||||
-- This is a copy of C_DATE from ISE's time cluster. I copied
|
||||
-- it to my support cluster so I can use it in my temporal and
|
||||
-- other projects without the overhead of using all of ISE's
|
||||
-- time cluster.
|
||||
|
||||
inherit
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
make_utc
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance of C_DATA using current local time.
|
||||
do
|
||||
is_utc := False
|
||||
update
|
||||
end
|
||||
|
||||
make_utc
|
||||
-- Create an instance of C_DATE holding UTC values.
|
||||
do
|
||||
is_utc := True
|
||||
update
|
||||
ensure
|
||||
is_utc: is_utc
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_utc: BOOLEAN
|
||||
-- Is Current holding value in UTC format?
|
||||
|
||||
feature -- Update
|
||||
|
||||
update
|
||||
-- Pointer to `struct tm' area.
|
||||
local
|
||||
l_timeb, l_tm, l_time: POINTER
|
||||
l_milli: INTEGER
|
||||
do
|
||||
l_timeb := l_timeb.memory_alloc (timeb_structure_size)
|
||||
l_time := l_time.memory_alloc (time_t_structure_size)
|
||||
ftime (l_timeb)
|
||||
get_time (l_timeb, l_time)
|
||||
if is_utc then
|
||||
l_tm := gmtime (l_time)
|
||||
else
|
||||
l_tm := localtime (l_time)
|
||||
end
|
||||
create internal_item.make_from_pointer (l_tm, tm_structure_size)
|
||||
|
||||
l_milli := get_millitm (l_timeb)
|
||||
if l_milli < 0 or l_milli > 999 then
|
||||
millisecond_now := 0
|
||||
else
|
||||
millisecond_now := l_milli
|
||||
end
|
||||
|
||||
l_timeb.memory_free
|
||||
l_time.memory_free
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
year_now: INTEGER
|
||||
-- Current year at creation time or after last call to `update'.
|
||||
do
|
||||
Result := 1900 + get_tm_year (internal_item.item)
|
||||
ensure
|
||||
year_valid: Result >= 1900
|
||||
end
|
||||
|
||||
month_now: INTEGER
|
||||
-- Current month at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_mon (internal_item.item) + 1
|
||||
ensure
|
||||
month_valid: Result >= 1 and Result <= 12
|
||||
end
|
||||
|
||||
day_now: INTEGER
|
||||
-- Current day at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_mday (internal_item.item)
|
||||
ensure
|
||||
day_valid: Result >= 1 and Result <= 31
|
||||
end
|
||||
|
||||
hour_now: INTEGER
|
||||
-- Current hour at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_hour (internal_item.item)
|
||||
ensure
|
||||
hour_valid: Result >= 0 and Result <= 23
|
||||
end
|
||||
|
||||
minute_now: INTEGER
|
||||
-- Current minute at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_min (internal_item.item)
|
||||
ensure
|
||||
minute_valid: Result >= 0 and Result <= 59
|
||||
end
|
||||
|
||||
second_now: INTEGER
|
||||
-- Current second at creation time or after last call to `update'.
|
||||
do
|
||||
Result := get_tm_sec (internal_item.item)
|
||||
if Result > 59 then
|
||||
-- Some platform returns up to 61 for leap seconds.
|
||||
Result := 59
|
||||
end
|
||||
ensure
|
||||
second_valid: Result >= 0 and Result <= 59
|
||||
end
|
||||
|
||||
millisecond_now: INTEGER
|
||||
-- Current millisecond at creation time or after last call to `update'.
|
||||
|
||||
feature {NONE} -- Externals
|
||||
|
||||
ftime (p: POINTER)
|
||||
-- Set current date and time in `p', pointer to a `struct timeb' area.
|
||||
external
|
||||
"C macro signature (struct timeb*) use <sys/timeb.h>"
|
||||
end
|
||||
|
||||
feature {NONE} -- `struct timeb' encapsulation
|
||||
|
||||
timeb_structure_size: INTEGER
|
||||
-- Size of `struct timeb'.
|
||||
external
|
||||
"C macro use <sys/timeb.h>"
|
||||
alias
|
||||
"sizeof(struct timeb)"
|
||||
end
|
||||
|
||||
time_t_structure_size: INTEGER
|
||||
-- Size of `struct timeb'.
|
||||
external
|
||||
"C macro use <time.h>"
|
||||
alias
|
||||
"sizeof(time_t)"
|
||||
end
|
||||
|
||||
tm_structure_size: INTEGER
|
||||
-- Size of `struct tm'.
|
||||
external
|
||||
"C macro use <time.h>"
|
||||
alias
|
||||
"sizeof(struct tm)"
|
||||
end
|
||||
|
||||
get_millitm (p: POINTER): INTEGER
|
||||
-- Get `p->millitm'.
|
||||
external
|
||||
"C struct struct timeb access millitm use <sys/timeb.h>"
|
||||
end
|
||||
|
||||
get_time (p, t: POINTER)
|
||||
-- Get `p->time'.
|
||||
external
|
||||
"C inline use <sys/timeb.h>, <time.h>"
|
||||
alias
|
||||
"*(time_t *) $t = (((struct timeb *)$p)->time);"
|
||||
end
|
||||
|
||||
feature {NONE} -- `struct tm' encapsulation
|
||||
|
||||
internal_item: MANAGED_POINTER
|
||||
-- Pointer to `struct tm' area.
|
||||
|
||||
localtime (t: POINTER): POINTER
|
||||
-- Pointer to `struct tm' area.
|
||||
external
|
||||
"C inline use <time.h>"
|
||||
alias
|
||||
"localtime ((time_t *) $t)"
|
||||
end
|
||||
|
||||
gmtime (t: POINTER): POINTER
|
||||
-- Pointer to `struct tm' area in UTC.
|
||||
external
|
||||
"C inline use <time.h>"
|
||||
alias
|
||||
"gmtime ((time_t *) $t)"
|
||||
end
|
||||
|
||||
get_tm_year (p: POINTER): INTEGER
|
||||
-- Get `p->tm_year', number of years since 1900.
|
||||
external
|
||||
"C struct struct tm access tm_year use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_mon (p: POINTER): INTEGER
|
||||
-- Get `p->tm_mon'.
|
||||
external
|
||||
"C struct struct tm access tm_mon use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_mday (p: POINTER): INTEGER
|
||||
-- Get `p->tm_mday'.
|
||||
external
|
||||
"C struct struct tm access tm_mday use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_hour (p: POINTER): INTEGER
|
||||
-- Get `p->tm_hour'.
|
||||
external
|
||||
"C struct struct tm access tm_hour use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_min (p: POINTER): INTEGER
|
||||
-- Get `p->tm_min'.
|
||||
external
|
||||
"C struct struct tm access tm_min use <time.h>"
|
||||
end
|
||||
|
||||
get_tm_sec (p: POINTER): INTEGER
|
||||
-- Get `p->tm_sec'.
|
||||
external
|
||||
"C struct struct tm access tm_sec use <time.h>"
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "Copyright (c) 1984-2006, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
356 Storke Road, Goleta, CA 93117 USA
|
||||
Telephone 805-685-1006, Fax 805-685-6869
|
||||
Website http://www.eiffel.com
|
||||
Customer support http://support.eiffel.com
|
||||
]"
|
||||
|
||||
|
||||
|
||||
|
||||
end -- class C_DATE
|
34
jj_temporal/jj_t/classes/hms_constants.e
Normal file
34
jj_temporal/jj_t/classes/hms_constants.e
Normal file
@ -0,0 +1,34 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with HMS_TIME, HMS_DURATION, and HMS_INTERVAL.
|
||||
]"
|
||||
date: "24 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
|
||||
class
|
||||
HMS_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_second: HMS_DURATION
|
||||
once
|
||||
create Result.set (0, 0, 1)
|
||||
end
|
||||
|
||||
One_minute: HMS_DURATION
|
||||
once
|
||||
create Result.set (0, 1, 0)
|
||||
end
|
||||
|
||||
One_hour: HMS_DURATION
|
||||
once
|
||||
create Result.set (1, 0, 0)
|
||||
end
|
||||
|
||||
end -- class HMS_CONSTANTS
|
281
jj_temporal/jj_t/classes/hms_duration.e
Normal file
281
jj_temporal/jj_t/classes/hms_duration.e
Normal file
@ -0,0 +1,281 @@
|
||||
note
|
||||
description: "[
|
||||
A duration of time represented by hours, minutes, and seconds.
|
||||
]"
|
||||
names: "duration, time_duration"
|
||||
date: "1999/01/01"; updated: "14 Aug 04"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_DURATION
|
||||
|
||||
create
|
||||
default_create,
|
||||
set,
|
||||
set_fine
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := hours.out + ":" + minutes.out + ":" + seconds.out + "." + milliseconds.out
|
||||
end
|
||||
|
||||
hours: INTEGER
|
||||
-- The number of hours in this DURATION
|
||||
|
||||
minutes: INTEGER
|
||||
-- The number of minutes in this DURATION
|
||||
|
||||
seconds: INTEGER
|
||||
-- The number of seconds in this DURATION
|
||||
|
||||
milliseconds: INTEGER
|
||||
-- The number of milli-seconds in this DURATION
|
||||
|
||||
as_hours: DOUBLE
|
||||
-- Length of this duration in hours.
|
||||
do
|
||||
Result := hours + minutes / 60 + seconds / 3600 + milliseconds / 3600000
|
||||
end
|
||||
|
||||
as_minutes: DOUBLE
|
||||
-- Length of this duration in minutes.
|
||||
do
|
||||
Result := hours * 60 + minutes + seconds / 60 + milliseconds / 60000
|
||||
end
|
||||
|
||||
as_seconds: DOUBLE
|
||||
-- Length of this duration in seconds.
|
||||
do
|
||||
Result := hours * 3600 + minutes * 60 + seconds + milliseconds / 1000
|
||||
end
|
||||
|
||||
as_milliseconds: DOUBLE
|
||||
-- Length of this duration in milliseconds
|
||||
do
|
||||
Result := hours * 3600000 + minutes * 60000 + seconds * 1000 + milliseconds
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for '*' and '/'.
|
||||
do
|
||||
create Result.set_fine (1, 1, 1, 1)
|
||||
ensure then
|
||||
result_hours_is_one: Result.hours = 1
|
||||
result_minutes_is_one: Result.minutes = 1
|
||||
result_seconds_is_one: Result.seconds = 1
|
||||
result_millisecons_is_one: Result.milliseconds = 1
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for '+' and '-'.
|
||||
do
|
||||
create Result
|
||||
ensure then
|
||||
result_hours_is_zero: Result.hours = 0
|
||||
result_minutes_is_zero: Result.minutes = 0
|
||||
result_seconds_is_zero: Result.seconds = 0
|
||||
result_milliseconds_is_zero: Result.milliseconds = 0
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
do
|
||||
-- Used minutes because it seemed reasonable accuracy.
|
||||
Result := as_minutes / other.as_minutes
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_zero
|
||||
-- Make current have zero length.
|
||||
do
|
||||
set_fine (0, 0, 0, 0)
|
||||
end
|
||||
|
||||
set (a_hours, a_minutes, a_seconds: INTEGER)
|
||||
-- Change the hours, minutes, and seconds to these values
|
||||
-- and set milliseconds to zero.
|
||||
do
|
||||
set_fine (a_hours, a_minutes, a_seconds, 0)
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
minutes_set: minutes = a_minutes
|
||||
seconds_set: seconds = a_seconds
|
||||
milliseconds_zero: milliseconds = 0
|
||||
end
|
||||
|
||||
set_fine (a_hours, a_minutes, a_seconds, a_milliseconds: INTEGER)
|
||||
-- Change `hours', `minutes', `seconds', and `milliseconds'
|
||||
do
|
||||
hours := a_hours
|
||||
minutes := a_minutes
|
||||
seconds := a_seconds
|
||||
milliseconds := a_milliseconds
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
minutes_set: minutes = a_minutes
|
||||
seconds_set: seconds = a_seconds
|
||||
milliseconds_set: milliseconds = a_milliseconds
|
||||
end
|
||||
|
||||
set_hours (a_hours: INTEGER)
|
||||
-- Change hours
|
||||
do
|
||||
hours := a_hours
|
||||
ensure
|
||||
hours_set: hours = a_hours
|
||||
end
|
||||
|
||||
set_minutes (a_minutes: INTEGER)
|
||||
-- change minutes
|
||||
do
|
||||
minutes := a_minutes
|
||||
ensure
|
||||
minutes_set: minutes = a_minutes
|
||||
end
|
||||
|
||||
set_seconds (a_seconds: INTEGER)
|
||||
-- Change seconds
|
||||
do
|
||||
seconds := a_seconds
|
||||
ensure
|
||||
seconds_set: seconds = a_seconds
|
||||
end
|
||||
|
||||
negate
|
||||
-- Reverses the sign for hours, minutes, and seconds.
|
||||
do
|
||||
hours := -hours
|
||||
minutes := -minutes
|
||||
seconds := -seconds
|
||||
milliseconds := -milliseconds
|
||||
ensure then
|
||||
hours_negated: -hours = old hours
|
||||
minutes_negated: -minutes = old minutes
|
||||
seconds_negated: -seconds = old seconds
|
||||
milliseconds_negated: milliseconds = -milliseconds
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "61 minutes" becomes "1 hour, 1 minute".
|
||||
do
|
||||
-- Fix me !!! for negatives...
|
||||
seconds := seconds + milliseconds // 999
|
||||
milliseconds := milliseconds \\ 999
|
||||
minutes := minutes + seconds // 60
|
||||
seconds := seconds \\ 60
|
||||
hours := hours + minutes // 60
|
||||
minutes := minutes \\ 60
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add 'other'. Does not 'normalize'.
|
||||
do
|
||||
hours := hours + other.hours
|
||||
minutes := minutes + other.minutes
|
||||
seconds := seconds + other.seconds
|
||||
milliseconds := milliseconds + other.milliseconds
|
||||
ensure then
|
||||
hours_added: hours = old hours + other.hours
|
||||
minutes_added: minutes = old minutes + other.minutes
|
||||
seconds_added: seconds = old seconds + other.seconds
|
||||
milliseconds_added: milliseconds = old milliseconds + other.milliseconds
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract 'other'. Does not 'normalize'.
|
||||
do
|
||||
hours := hours - other.hours
|
||||
minutes := minutes - other.minutes
|
||||
seconds := seconds - other.seconds
|
||||
milliseconds := milliseconds - other.milliseconds
|
||||
ensure then
|
||||
hours_subbed: hours = old hours - other.hours
|
||||
minutes_subbed: minutes = old minutes - other.minutes
|
||||
seconds_subbed: seconds = old seconds - other.seconds
|
||||
milliseconds_subbed: milliseconds = old milliseconds - other.milliseconds
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
-- Multiply `hours'
|
||||
v := hours * r
|
||||
hours := v.floor
|
||||
fract := v - hours
|
||||
-- Multiply `minutes' and add fractional of hour
|
||||
v := minutes * r + 60 * fract
|
||||
minutes := v.floor
|
||||
fract := v - minutes
|
||||
-- Mulitply `seconds' and add fractional minute
|
||||
v := seconds * r + 60 * fract
|
||||
seconds := v.floor
|
||||
fract := v - seconds
|
||||
-- Multiply `milliseconds' and add fractional second
|
||||
v := milliseconds * r + 1000 * fract
|
||||
milliseconds := v.rounded
|
||||
-- Normalize
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set_fine (0, 0, 0, (as_milliseconds / r).rounded)
|
||||
normalize
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_seconds.truncated_to_integer // i)
|
||||
normalize
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_seconds.truncated_to_integer \\ i)
|
||||
normalize
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is 'Current' less than 'other'?
|
||||
local
|
||||
temp, temp_other: like Current
|
||||
do
|
||||
temp := twin
|
||||
temp_other := other.twin
|
||||
temp.normalize
|
||||
temp_other.normalize
|
||||
Result := (temp.hours < temp_other.hours) or
|
||||
(temp.hours = temp_other.hours and temp.minutes < temp_other.minutes) or
|
||||
(temp.hours = temp_other.hours and temp.minutes = temp_other.minutes and temp.seconds < temp_other.seconds)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
68
jj_temporal/jj_t/classes/hms_interval.e
Normal file
68
jj_temporal/jj_t/classes/hms_interval.e
Normal file
@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time
|
||||
and duration described in terms of hours, minutes, and
|
||||
seconds. Positive durations only.
|
||||
]"
|
||||
names: "hms_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance starting and ending at the default creation
|
||||
-- value for the type of `start' time, having zero length duration.
|
||||
do
|
||||
-- Can't define `default_create' in ABSTRACT_INTERVAL because there
|
||||
-- `start_imp' is deffered and cannot call create on a deferred type.
|
||||
create start_imp
|
||||
finish_imp := start_imp.twin
|
||||
ensure then
|
||||
same_start_and_finish: equal (start, finish)
|
||||
zero_duration: duration.is_zero
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
551
jj_temporal/jj_t/classes/hms_time.e
Normal file
551
jj_temporal/jj_t/classes/hms_time.e
Normal file
@ -0,0 +1,551 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time as on a clock. An
|
||||
Hour, Minute, Second time (ie. a time).
|
||||
]"
|
||||
names: "time"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIME
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_TIME
|
||||
rename
|
||||
as_integer as as_seconds
|
||||
redefine
|
||||
default_create,
|
||||
is_valid,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
set,
|
||||
set_fine,
|
||||
from_seconds,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with time 00:00:00 (i.e. midnight).
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
hour: INTEGER
|
||||
-- Hour part of time.
|
||||
|
||||
minute: INTEGER
|
||||
-- Minute part of time.
|
||||
|
||||
second: INTEGER
|
||||
-- Second part of time.
|
||||
|
||||
millisecond: INTEGER
|
||||
-- Millisecond part of the time.
|
||||
|
||||
overflow: INTEGER
|
||||
-- Number of days after a normalize (49 hours gives 2 days overflow).
|
||||
|
||||
as_string: STRING
|
||||
-- The time represented as a string with no seperator characters, such
|
||||
-- as ":", "-", or "/". The time 23:59:59.999 becomes "235959.999"
|
||||
do
|
||||
create Result.make (10)
|
||||
if not (hour >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (hour.out)
|
||||
if not (minute >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (minute.out)
|
||||
if not (second >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (second.out)
|
||||
Result.append (".")
|
||||
if not (millisecond >= 100) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (millisecond >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (millisecond.out)
|
||||
end
|
||||
|
||||
as_seconds: INTEGER
|
||||
-- The number of seconds from midnight to the current time.
|
||||
-- `Millisecond' is rounded.
|
||||
do
|
||||
Result := hour * 60 * 60 + minute * 60 + second + (millisecond / 1000).rounded
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
h, m, s, mil: INTEGER
|
||||
do
|
||||
h := a_string.substring (1, 2).to_integer
|
||||
m := a_string.substring (3, 4).to_integer
|
||||
s := a_string.substring (5, 6).to_integer
|
||||
mil := a_string.substring (8, 10).to_integer
|
||||
set_fine (h, m, s, mil)
|
||||
end
|
||||
|
||||
from_seconds (a_seconds: INTEGER)
|
||||
-- Initialize as `a_seconds' from midnight.
|
||||
do
|
||||
set (0, 0, 0)
|
||||
add_seconds (a_seconds)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Set current time according to timezone, setting `millisecond' to zero.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, 0)
|
||||
end
|
||||
|
||||
set_now_fine
|
||||
-- Set current time according to timezone, including milli-seconds.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, C_date.millisecond_now)
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- The `millisecond' is set to zero.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.hour_now, C_date.minute_now, C_date.second_now)
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format, including `millisecond'.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set_fine (C_date.hour_now, C_date.minute_now, C_date.second_now, C_date.millisecond_now)
|
||||
end
|
||||
|
||||
set (h, m, s: INTEGER)
|
||||
-- Change the hour, minute, and second.
|
||||
-- Set `millisecond' to 0.
|
||||
require
|
||||
hour_valid: 0 <= h and h <= 23;
|
||||
minute_valid: 0 <= m and m <= 59;
|
||||
second_valid: 0 <= s and s <= 59
|
||||
do
|
||||
set_fine (h, m, s, 0)
|
||||
ensure
|
||||
hour_assigned: hour = h
|
||||
minute_assigned: minute = m
|
||||
second_assigned: second = s
|
||||
millisecond_assigned: millisecond = 0
|
||||
end
|
||||
|
||||
set_fine (h, m, s, mil: INTEGER)
|
||||
-- Change the hour, minute, and second
|
||||
require
|
||||
hour_valid: 0 <= h and h <= 23
|
||||
minute_valid: 0 <= m and m <= 59
|
||||
second_valid: 0 <= s and s <= 59
|
||||
millisecond_valid: 0 <= mil and mil <= 999999
|
||||
do
|
||||
hour := h;
|
||||
minute := m;
|
||||
second := s;
|
||||
millisecond := mil
|
||||
ensure
|
||||
hour_assigned: hour = h
|
||||
minute_assigned: minute = m
|
||||
second_assigned: second = s
|
||||
millisecond_assigned: millisecond = mil
|
||||
end
|
||||
|
||||
set_hour (a_hour: INTEGER)
|
||||
-- Change the `hour'.
|
||||
require
|
||||
hour_valid: 0 <= a_hour and a_hour <= 23;
|
||||
do
|
||||
hour := a_hour
|
||||
ensure
|
||||
hour_assigned: hour = a_hour
|
||||
end
|
||||
|
||||
set_minute (a_minute: INTEGER)
|
||||
-- Change the `minute'.
|
||||
require
|
||||
minute_valid: 0 <= a_minute and a_minute <= 59;
|
||||
do
|
||||
minute := a_minute
|
||||
ensure
|
||||
minute_assigned: minute = a_minute
|
||||
end
|
||||
|
||||
set_second (a_second: INTEGER)
|
||||
-- Change the second.
|
||||
require
|
||||
second_valid: 0 <= a_second and a_second <= 59
|
||||
do
|
||||
second := a_second
|
||||
ensure
|
||||
second_assigned: second = a_second
|
||||
end
|
||||
|
||||
set_millisecond (a_millisecond: INTEGER)
|
||||
-- Change the `millisecond'
|
||||
require
|
||||
valid_millisecond: 0 <= a_millisecond and a_millisecond <= 999
|
||||
do
|
||||
millisecond := a_millisecond
|
||||
ensure
|
||||
millisecond_assigned: millisecond = a_millisecond
|
||||
end
|
||||
|
||||
from_integer (a_integer: INTEGER)
|
||||
-- Change Current to the time represented by `a_integer'.
|
||||
-- `A_compact_time' must represent a date that is not BC.
|
||||
do
|
||||
-- Fix me !!!
|
||||
end
|
||||
|
||||
clear_overflow
|
||||
-- Remove the `overflow' condition by seting overflow to 0.
|
||||
-- (Overflows occur when `add_duration' causes the time to be past 23:59:59.999)
|
||||
do
|
||||
overflow := 0
|
||||
end
|
||||
|
||||
truncate_to_hours
|
||||
-- Reset "to the hour" (set minutes and seconds to 0).
|
||||
do
|
||||
set_fine (hour, 0, 0, 0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
truncate_to_minutes
|
||||
-- Reset "to the minute" (i.e. set seconds to 0.)
|
||||
do
|
||||
set_fine (hour, minute, 0, 0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_unchanged: minute = old minute
|
||||
second_zero: second = 0
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
truncate_to_seconds
|
||||
-- Set the `millisecond' to zero.
|
||||
-- Use when `millisecond' portion is to be ignored.
|
||||
do
|
||||
set_millisecond (0)
|
||||
ensure
|
||||
hour_unchanged: hour = old hour
|
||||
minute_unchanged: minute = old minute
|
||||
second_unchaged: second = old second
|
||||
millisecond_zero: millisecond = 0
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this time come before 'other'?
|
||||
require else
|
||||
other_time_not_void: other /= Void
|
||||
do
|
||||
Result := hour < other.hour or else
|
||||
(hour = other.hour) and (minute < other.minute) or else
|
||||
(hour = other.hour) and (minute = other.minute) and (second < other.second) or else
|
||||
(hour = other.hour) and (minute = other.minute) and (second = other.second) and (millisecond < other.millisecond)
|
||||
ensure then
|
||||
-- definition: Result = (hour < other.hour) or else
|
||||
-- (hour = other.hour) and (minute < other.minute) or else
|
||||
-- (hour = other.hour) and (minute = other.minute) and (second < other.second) or else
|
||||
-- (hour = other.hour) and (minute = other.minute) and (second = other.second) and (millisecond < other.millisecond)
|
||||
end
|
||||
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_duration (a_duration: like Duration_anchor)
|
||||
-- Add a length of time (in hours, minutes, and seconds) to the time.
|
||||
do
|
||||
-- hour := hour + a_duration.hours
|
||||
-- minute := minute + a_duration.minutes
|
||||
-- second := second + a_duration.seconds
|
||||
-- millisecond := millisecond + a_duration.milliseconds
|
||||
add_milliseconds (a_duration.milliseconds)
|
||||
add_seconds (a_duration.seconds)
|
||||
add_minutes (a_duration.minutes)
|
||||
add_hours (a_duration.hours)
|
||||
end
|
||||
|
||||
add_hours (a_number: INTEGER)
|
||||
-- Add `a_number' of hours to the current time
|
||||
local
|
||||
h: INTEGER
|
||||
do
|
||||
h := a_number \\ 24
|
||||
hour := hour + h
|
||||
check
|
||||
number_now_even: (a_number - h) \\ 24 = 0
|
||||
end
|
||||
overflow := (a_number - h) // 24
|
||||
if hour < 0 then
|
||||
check
|
||||
positive_overflow: overflow >= 1
|
||||
end
|
||||
hour := hour + 24
|
||||
overflow := overflow - 1
|
||||
end
|
||||
if hour >= 24 then
|
||||
hour := hour - 24
|
||||
overflow := overflow + 1
|
||||
end
|
||||
end
|
||||
|
||||
add_minutes (a_number: INTEGER)
|
||||
-- Add `a_number' of minutes to the current time.
|
||||
local
|
||||
m: INTEGER
|
||||
do
|
||||
minute := minute + a_number
|
||||
m := minute
|
||||
minute := minute \\ 60
|
||||
if minute < 0 then
|
||||
minute := minute + 60
|
||||
add_hours (-1)
|
||||
end
|
||||
add_hours (m // 60)
|
||||
end
|
||||
|
||||
add_seconds (a_number: INTEGER)
|
||||
-- Add `a_number' of seconds to the current time.
|
||||
local
|
||||
s: INTEGER
|
||||
do
|
||||
second := second + a_number
|
||||
s := second
|
||||
second := second \\ 60
|
||||
if second < 0 then
|
||||
second := second + 60
|
||||
add_minutes (-1)
|
||||
end
|
||||
add_minutes (s // 60)
|
||||
end
|
||||
|
||||
add_milliseconds (a_number: INTEGER)
|
||||
-- Add `a_number' of milliseconds to the current time.
|
||||
local
|
||||
ms: INTEGER
|
||||
do
|
||||
millisecond := millisecond + a_number
|
||||
ms := millisecond
|
||||
millisecond := millisecond \\ 1000
|
||||
if millisecond < 0 then
|
||||
millisecond := millisecond + 1000
|
||||
add_seconds (-1)
|
||||
end
|
||||
add_seconds (ms // 1000)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
-- Caveat: the `milliseconds' will be lost due to rounding in `as_seconds'.
|
||||
do
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
time_between (other: like Current): like Duration_anchor
|
||||
-- A length of time in hours, minutes, and seconds
|
||||
-- between this time and other.
|
||||
local
|
||||
larger, smaller: like Current
|
||||
h, m, s, ms: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
ms := larger.millisecond - smaller.millisecond
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if ms < 0 then
|
||||
ms := ms + 999
|
||||
s := s - 1
|
||||
end
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
create Result.set_fine (h, m, s, ms)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
seconds_between (a_other: like Current): INTEGER
|
||||
-- The number of seconds between Current and `other'
|
||||
require
|
||||
other_exists: a_other /= Void
|
||||
local
|
||||
larger, smaller: like Current
|
||||
h, m, s, ms: INTEGER
|
||||
do
|
||||
larger := max (a_other)
|
||||
smaller := min (a_other)
|
||||
ms := larger.millisecond - smaller.millisecond
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if ms < 0 then
|
||||
ms := ms + 999
|
||||
s := s - 1
|
||||
end
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
Result := h * 60 * 60 + m * 60 + s
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
hs, ms, ss, mils: STRING
|
||||
h, m, s, mil: INTEGER
|
||||
do
|
||||
if a_string /= Void and then a_string.count = 10 and then equal (a_string.substring (7, 7), ".") then
|
||||
hs := a_string.substring (1, 2)
|
||||
ms := a_string.substring (3, 4)
|
||||
ss := a_string.substring (5, 6)
|
||||
mils := a_string.substring (8, 10)
|
||||
if hs.is_integer and then ms.is_integer and then ss.is_integer and then mils.is_integer then
|
||||
h := hs.to_integer
|
||||
m := ms.to_integer
|
||||
s := ms.to_integer
|
||||
mil := mils.to_integer
|
||||
if (h >= 0 and h <= 23) and then
|
||||
(m >= 0 and m <= 59) and then
|
||||
(s >= 0 and s <= 59) and then
|
||||
(mil >= 0 and mil <= 999) then
|
||||
Result := True
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
do
|
||||
Result := a_integer >= 0
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
-- normalize is
|
||||
-- -- convert to a normal time (1 minute, 60 seconds becomes 2 minutes 0 seconds)
|
||||
-- do
|
||||
-- second := second + millisecond // 999
|
||||
-- millisecond := millisecond \\ 999
|
||||
-- if millisecond < 0 then
|
||||
-- millisecond := millisecond + 999
|
||||
-- second := second - 1
|
||||
-- end
|
||||
-- minute := minute + second // 60
|
||||
-- second := second \\ 60
|
||||
-- if second < 0 then
|
||||
-- second := second + 60
|
||||
-- minute := minute - 1
|
||||
-- end
|
||||
-- hour := hour + minute // 60
|
||||
-- minute := minute \\ 60
|
||||
-- if minute < 0 then
|
||||
-- minute := minute + 60
|
||||
-- hour := hour - 1
|
||||
-- end
|
||||
-- overflow := hour // 24
|
||||
-- hour := hour \\ 24
|
||||
-- if hour < 0 then
|
||||
-- hour := hour + 24
|
||||
-- overflow := overflow - 1
|
||||
-- end
|
||||
-- end
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is time in correct format?
|
||||
do
|
||||
Result := (0 <= millisecond and millisecond <= 999) and
|
||||
(0 <= second and second <= 59) and
|
||||
(0 <= minute and minute <= 59) and
|
||||
(0 <= hour and hour <= 23)
|
||||
ensure then
|
||||
valid_result: Result implies
|
||||
(0 <= millisecond and millisecond <= 999) and
|
||||
(0 <= second and second <= 59) and
|
||||
(0 <= minute and minute <= 59) and
|
||||
(0 <= hour and hour <= 23)
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: HMS_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
74
jj_temporal/jj_t/classes/hms_timer.e
Normal file
74
jj_temporal/jj_t/classes/hms_timer.e
Normal file
@ -0,0 +1,74 @@
|
||||
note
|
||||
description: "[
|
||||
Timer for hours, minutes, seconds, and miliseconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_INTERVAL
|
||||
undefine
|
||||
duration,
|
||||
out
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {HMS_INTERVAL}
|
||||
Precursor {TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: HMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
60
jj_temporal/jj_t/classes/time_stampable.e
Normal file
60
jj_temporal/jj_t/classes/time_stampable.e
Normal file
@ -0,0 +1,60 @@
|
||||
note
|
||||
description: "[
|
||||
Objects which record their creation time.
|
||||
]"
|
||||
date: "1 Sep 04"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
TIME_STAMPABLE
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
create timestamp.set_now_utc_fine
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
id: STRING
|
||||
-- Unique (hopefully) object id based on the creation time of the object.
|
||||
-- Concatination of Current's `generating_type' and `time_stamp'.
|
||||
do
|
||||
Result := generating_type.name.to_string_8 + " " + timestamp.as_string
|
||||
end
|
||||
|
||||
timestamp: YMDHMS_TIME
|
||||
-- Time this object was created
|
||||
|
||||
--feature -- Comparison
|
||||
|
||||
-- infix "<" (a_other: like Current): BOOLEAN is
|
||||
-- -- Is Current less than `a_other'?
|
||||
-- do
|
||||
-- Result := id < a_other.id
|
||||
---- Result := timestamp < a_other.timestamp
|
||||
-- end
|
||||
|
||||
invariant
|
||||
|
||||
time_stamp_exists: timestamp /= Void
|
||||
|
||||
end
|
122
jj_temporal/jj_t/classes/timer.e
Normal file
122
jj_temporal/jj_t/classes/timer.e
Normal file
@ -0,0 +1,122 @@
|
||||
note
|
||||
description: "[
|
||||
Stop-watch type object.
|
||||
Create the object and call `reset' to use.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
deferred class
|
||||
TIMER
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
duration
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Initialize Current
|
||||
do
|
||||
create lap_times.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
duration: like duration_anchor
|
||||
-- The time between the `start' and the `finish';
|
||||
-- or the time between the `start' and the current time if
|
||||
-- the timer is running.
|
||||
local
|
||||
t: like time_anchor
|
||||
do
|
||||
if is_running then
|
||||
t := finish
|
||||
t.set_now_utc_fine
|
||||
Result := t.time_between (start)
|
||||
else
|
||||
Result := Precursor
|
||||
end
|
||||
end
|
||||
|
||||
cumulative: like duration_anchor
|
||||
-- Cumulative total of all the times elapsed on the timer.
|
||||
-- Recalculated at every `stop'.
|
||||
|
||||
i_th_lap (a_index: INTEGER): like duration_anchor
|
||||
-- The `a_index'th duration.
|
||||
require
|
||||
is_valid_lap_index: is_valid_lap_index (a_index)
|
||||
do
|
||||
Result := lap_times.i_th (a_index)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_running: BOOLEAN
|
||||
-- Is the timer running?
|
||||
-- (Use `start' to begin timing and `stop' to end.)
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
reset
|
||||
-- Reset `elapsed' to zero.
|
||||
do
|
||||
start_imp.set_now_utc_fine
|
||||
finish_imp.copy (start)
|
||||
cumulative.set_zero
|
||||
lap_times.wipe_out
|
||||
end
|
||||
|
||||
run
|
||||
-- Start the timer
|
||||
require
|
||||
not_running: not is_running
|
||||
do
|
||||
is_running := True
|
||||
start_imp.set_now_utc_fine
|
||||
ensure
|
||||
is_running: is_running
|
||||
end
|
||||
|
||||
stop
|
||||
-- Stop the timer
|
||||
require
|
||||
is_running: is_running
|
||||
do
|
||||
is_running := False
|
||||
finish_imp.set_now_utc_fine
|
||||
cumulative := cumulative + duration
|
||||
-- start_imp.copy (finish)
|
||||
-- mark_lap
|
||||
ensure
|
||||
is_stopped: not is_running
|
||||
end
|
||||
|
||||
mark_lap
|
||||
-- Record the current `lap' time in `lap_times' but keep the timer running.
|
||||
do
|
||||
lap_times.extend (duration)
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_valid_lap_index (a_index: INTEGER): BOOLEAN
|
||||
-- Is `a_index' a valid value into the list of `lap_times'?
|
||||
do
|
||||
Result := lap_times.valid_index (a_index)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
lap_times: ARRAYED_LIST [like duration_anchor]
|
||||
-- List of durations for each time `mark_lap' was called.
|
||||
|
||||
end
|
48
jj_temporal/jj_t/classes/ymd_constants.e
Normal file
48
jj_temporal/jj_t/classes/ymd_constants.e
Normal file
@ -0,0 +1,48 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with YMD_TIME, YMD_DURATION, and YMD_INTERVAL.
|
||||
]"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_day: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 1)
|
||||
end
|
||||
|
||||
One_week: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 7)
|
||||
end
|
||||
|
||||
One_month: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 1, 0)
|
||||
end
|
||||
|
||||
One_quarter: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 3, 0)
|
||||
end
|
||||
|
||||
One_year: YMD_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (1, 0, 0)
|
||||
end
|
||||
|
||||
end -- class YMD_CONSTANTS
|
325
jj_temporal/jj_t/classes/ymd_duration.e
Normal file
325
jj_temporal/jj_t/classes/ymd_duration.e
Normal file
@ -0,0 +1,325 @@
|
||||
note
|
||||
description: "[
|
||||
Duration of time described in years, months, and days.
|
||||
]"
|
||||
names: "ymd_duration"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_DURATION
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with zero length.
|
||||
do
|
||||
days_per_month := default_days_per_month
|
||||
set (0, 0, 0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := years.out + ":" + months.out + ":" + days.out
|
||||
end
|
||||
|
||||
years: INTEGER
|
||||
-- Number of years part.
|
||||
-- Does not consider the months or days.
|
||||
|
||||
months: INTEGER
|
||||
-- Number of months part.
|
||||
-- Does not consider the years or days.
|
||||
|
||||
days: INTEGER
|
||||
-- Number of days part.
|
||||
-- Does not consider the months or years.
|
||||
|
||||
default_days_per_month: DOUBLE = 30.4375
|
||||
-- Default value for 'days_per_month'.
|
||||
-- 365.25 days per year divided by 12 months per year.
|
||||
|
||||
days_per_month: DOUBLE
|
||||
-- Number of days in a month. (28?, 29?, 30?, 31?)
|
||||
-- Value assumed by class to do calculations involving conversion
|
||||
-- from days to months to years.
|
||||
-- Default = 30.4375 days / month.
|
||||
|
||||
days_per_year: DOUBLE
|
||||
-- Number of days in the year. Calculated based on 'days_per_month'.
|
||||
-- Value assumed by class to do calculations involving conversion
|
||||
-- from days to months to years.
|
||||
-- Default = 365.25 days / year.
|
||||
do
|
||||
Result := days_per_month * 12
|
||||
end
|
||||
|
||||
as_years: DOUBLE
|
||||
-- Length of duration in years.
|
||||
do
|
||||
Result := years + months / 12 + days / days_per_year
|
||||
end
|
||||
|
||||
as_months: DOUBLE
|
||||
-- Length of duration in months.
|
||||
do
|
||||
Result := years * 12 + months + days / days_per_month
|
||||
end
|
||||
|
||||
as_days: DOUBLE
|
||||
-- Length of duration in days.
|
||||
do
|
||||
Result := years * days_per_year + months * days_per_month + days
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
do
|
||||
create Result
|
||||
Result.set (1,1,1)
|
||||
ensure then
|
||||
result_years_is_one: Result.years = 1
|
||||
result_months_is_one: Result.months = 1
|
||||
result_days_is_one: Result.days = 1
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
do
|
||||
create Result
|
||||
ensure then
|
||||
result_years_is_zero: Result.years = 0
|
||||
result_months_is_zero: Result.months = 0
|
||||
result_days_is_zero: Result.days = 0
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
-- For example: is current duration at least twice as long as other?
|
||||
do
|
||||
-- Result := as_months / other.as_months -- Used months because it seemed reasonable accuracy.
|
||||
Result := as_days / other.as_days -- Must use days because of accuracy problems with month length.
|
||||
end
|
||||
|
||||
normalized: like Current
|
||||
-- A copy of Current in a normalized form.
|
||||
do
|
||||
Result := twin
|
||||
Result.normalize
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_zero
|
||||
-- Make Current have zero length.
|
||||
do
|
||||
set (0, 0, 0)
|
||||
end
|
||||
|
||||
set (ys, ms, ds: INTEGER)
|
||||
-- Change the length of years, months, and days.
|
||||
do
|
||||
years := ys
|
||||
months := ms
|
||||
days := ds
|
||||
ensure
|
||||
years_set: years = ys
|
||||
months_set: months = ms
|
||||
days_set: days = ds
|
||||
end
|
||||
|
||||
set_years (ys: INTEGER)
|
||||
-- Change years
|
||||
do
|
||||
years := ys
|
||||
ensure
|
||||
years_set: years = ys
|
||||
end
|
||||
|
||||
set_months (ms: INTEGER)
|
||||
-- Change months
|
||||
do
|
||||
months := ms;
|
||||
ensure
|
||||
months_set: months = ms
|
||||
end
|
||||
|
||||
set_days (ds: INTEGER)
|
||||
-- Change days
|
||||
do
|
||||
days := ds
|
||||
ensure
|
||||
days_set: days = ds
|
||||
end
|
||||
|
||||
set_days_per_month (i: DOUBLE)
|
||||
-- Change 'days_per_month' (value used in calculations
|
||||
-- involving month lenghts).
|
||||
require
|
||||
in_range: i >= 28 and i <= 31
|
||||
do
|
||||
days_per_month := i
|
||||
ensure
|
||||
days_per_month_set: days_per_month = i
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
negate
|
||||
-- Reverse the sign on years, months, and days.
|
||||
do
|
||||
years := -years;
|
||||
months := -months;
|
||||
days := -days
|
||||
ensure then
|
||||
years_negated: -years = old years
|
||||
months_negated: -months = old months
|
||||
days_negated: -days = old days
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "13 months" becomes "1 year, 1 month".
|
||||
-- Month and year length is based on 'days_per_month'.
|
||||
-- This feature is hard to define. For example, is 28 days equal to
|
||||
-- one month? What about 30 days?
|
||||
-- This needs to be fixed.
|
||||
require
|
||||
days_per_month > 0
|
||||
local
|
||||
m, d: DOUBLE
|
||||
dpm: DOUBLE
|
||||
do
|
||||
-- The check on `days_per_month' was necessary because `<' which calls
|
||||
-- this feature must be getting called before the object is fully
|
||||
-- initialized, so at that point `days_per_month' is zero; this check
|
||||
-- prevents that "floating point exception".
|
||||
if days_per_month = 0 then
|
||||
dpm := Default_days_per_month
|
||||
else
|
||||
dpm := days_per_month
|
||||
end
|
||||
d := days
|
||||
m := d / dpm
|
||||
months := months + m.truncated_to_integer
|
||||
m := m - m.truncated_to_integer
|
||||
d := m * dpm
|
||||
days := d.truncated_to_integer
|
||||
-- if (d - days) > 0.5 then
|
||||
-- days := days + 1
|
||||
-- if days > dpm then
|
||||
-- months := months + 1
|
||||
-- end
|
||||
-- end
|
||||
years := years + months // 12
|
||||
months := months \\ 12
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other to current.
|
||||
do
|
||||
years := years + other.years;
|
||||
months := months + other.months;
|
||||
days := days + other.days
|
||||
ensure then
|
||||
years_added: years = old years + other.years
|
||||
months_added: months = old months + other.months
|
||||
days_add: days = old days + other.days
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from current.
|
||||
do
|
||||
years := years - other.years;
|
||||
months := months - other.months;
|
||||
days := days - other.days
|
||||
ensure then
|
||||
years_subbed: years = old years - other.years
|
||||
months_subbed: months = old months - other.months
|
||||
days_subbed: days = old days - other.days
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
v := years * r
|
||||
years := v.floor
|
||||
fract := v - years
|
||||
|
||||
v := months * r + 12 * fract
|
||||
months := v.floor
|
||||
fract := v - months
|
||||
|
||||
v := days * r + days_per_month * fract
|
||||
days := v.rounded
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, (as_days / r).rounded)
|
||||
normalize
|
||||
end
|
||||
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, (as_days / i).truncated_to_integer)
|
||||
normalize
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo of duration with 'i'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
set (0, 0, as_days.truncated_to_integer \\ i)
|
||||
normalize
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is current shorter than other?
|
||||
local
|
||||
temp, temp_other: like Current
|
||||
do
|
||||
temp := twin
|
||||
temp_other := other.twin
|
||||
temp.normalize
|
||||
temp_other.normalize
|
||||
Result := (temp.years < temp_other.years) or else
|
||||
(temp.years = temp_other.years and temp.months < temp_other.months) or else
|
||||
(temp.years = temp_other.years and temp.months = temp_other.months and temp.days < temp_other.days)
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
days_per_month_in_range: days_per_month >= 28 and days_per_month <= 31
|
||||
|
||||
|
||||
end -- class YMD_DURATION
|
||||
|
67
jj_temporal/jj_t/classes/ymd_interval.e
Normal file
67
jj_temporal/jj_t/classes/ymd_interval.e
Normal file
@ -0,0 +1,67 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time and duration
|
||||
described in terms of years, months, and days. Positive durations only.
|
||||
]"
|
||||
names: "ymd_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance starting and ending at the default creation
|
||||
-- value for the type of `start' time, having zero length duration.
|
||||
do
|
||||
-- Can't define `default_create' in ABSTRACT_INTERVAL because there
|
||||
-- `start_imp' is deffered and cannot call create on a deferred type.
|
||||
create start_imp
|
||||
finish_imp := start_imp.twin
|
||||
ensure then
|
||||
same_start_and_finish: equal (start, finish)
|
||||
zero_duration: duration.is_zero
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
671
jj_temporal/jj_t/classes/ymd_time.e
Normal file
671
jj_temporal/jj_t/classes/ymd_time.e
Normal file
@ -0,0 +1,671 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time as on a gregorian callendar.
|
||||
Has a `Year', `Month', and `Day' (i.e. a date).
|
||||
]"
|
||||
names: "date, time"
|
||||
date: "1 Jan 99"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME
|
||||
|
||||
inherit
|
||||
|
||||
ABSTRACT_TIME
|
||||
rename
|
||||
as_integer as as_days,
|
||||
from_integer as from_days
|
||||
redefine
|
||||
default_create,
|
||||
is_valid,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set,
|
||||
from_days,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance based on todays date.
|
||||
do
|
||||
set_now
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
year: INTEGER
|
||||
-- Year part of the date.
|
||||
|
||||
month: INTEGER
|
||||
-- Month part of the date.
|
||||
|
||||
day: INTEGER
|
||||
-- Day part of the date.
|
||||
do
|
||||
Result := internal_day
|
||||
if Result > last_day_of_month then
|
||||
Result := last_day_of_month
|
||||
end
|
||||
end
|
||||
|
||||
week_number: INTEGER
|
||||
-- Week of the year containing this date.
|
||||
local
|
||||
d: YMD_TIME
|
||||
first_d: INTEGER -- Jan 1st is on what day?
|
||||
do
|
||||
create d
|
||||
d.set (year, 1, 1)
|
||||
first_d := d.weekday
|
||||
Result := (((julian + first_d - 1 - 1) // 7) + 1)
|
||||
ensure
|
||||
result_large_enough: Result >= 1
|
||||
result_small_enough: Result <= 54 -- 53 ? 54 if leapyear falls just right.
|
||||
end
|
||||
|
||||
last_day_of_month: INTEGER
|
||||
-- Date of last day for current month
|
||||
do
|
||||
inspect
|
||||
month
|
||||
when 2 then
|
||||
if is_leapyear then
|
||||
Result := 29
|
||||
else
|
||||
Result := 28
|
||||
end
|
||||
when 4, 6, 9, 11 then
|
||||
Result := 30
|
||||
else
|
||||
Result := 31
|
||||
end
|
||||
ensure
|
||||
day_in_range: Result >= 28 and Result <= 31
|
||||
good_not_leap: Result = 28 implies (month = 2 and not is_leapyear)
|
||||
good_in_leap: Result = 29 implies (month = 2 and is_leapyear)
|
||||
good_30s: Result = 30 implies (month = 4 or month = 6 or month = 9 or month = 11)
|
||||
good_31s: Result = 31 implies (month=1 or month=3 or month=5 or month=7 or month=8 or month=10 or month=12)
|
||||
end
|
||||
|
||||
days_remaining_this_month: INTEGER
|
||||
-- Number of days from current until end of month.
|
||||
-- Used in some calculations.
|
||||
do
|
||||
Result := last_day_of_month - day
|
||||
ensure
|
||||
valid_result: Result >= 0 and Result < last_day_of_month
|
||||
end
|
||||
|
||||
julian: INTEGER
|
||||
-- Day of the year between 1 and 366
|
||||
local
|
||||
n,i : INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i >= month
|
||||
loop
|
||||
inspect i
|
||||
when 2 then
|
||||
if is_leapyear then
|
||||
n := n + 29
|
||||
else
|
||||
n := n + 28
|
||||
end
|
||||
when 4,6,9,11 then
|
||||
n := n + 30
|
||||
else
|
||||
n := n + 31
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
result := n + day
|
||||
ensure
|
||||
valid_leapyear_result: is_leapyear implies (1 <= Result and Result <= 366)
|
||||
valid_result: not is_leapyear implies (1 <= Result and Result <= 365)
|
||||
end
|
||||
|
||||
|
||||
weekday: INTEGER
|
||||
-- 1 for Sunday, 2 for Monday, etc
|
||||
-- Only works as far back as ~2 Mar 0001. ???
|
||||
local
|
||||
x : INTEGER
|
||||
do
|
||||
x := internal\\7 + 1 + 1
|
||||
if x > 7 then -- it can only be 8
|
||||
x := 1
|
||||
end
|
||||
result := x
|
||||
ensure
|
||||
valid_weekday: 1 <= Result and Result <= 7
|
||||
end
|
||||
|
||||
as_string: STRING
|
||||
-- The date represented as a string with no spaces.
|
||||
-- 18 Jan 2005 would be "20050118".
|
||||
do
|
||||
create Result.make (10)
|
||||
if is_bc then
|
||||
Result.append ("BC")
|
||||
end
|
||||
if not (year.abs >= 1000) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (year.abs >= 100) then
|
||||
Result.append ("0")
|
||||
end
|
||||
if not (year.abs >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (year.abs.out)
|
||||
if not (month >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (month.out)
|
||||
if not (day >= 10) then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append (day.out)
|
||||
end
|
||||
|
||||
as_days: INTEGER
|
||||
-- The number of days from midnight (00:00:00)
|
||||
-- on 1 Jan 1970 to the beginning Current's `day'.
|
||||
local
|
||||
t: YMD_TIME
|
||||
do
|
||||
create t
|
||||
t.set (1970, 1, 1)
|
||||
Result := days_between (t)
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_days (a_days: INTEGER)
|
||||
-- Change Current to the time represented by `a_days'.
|
||||
-- `A_days' is assumed to be the number of days since 1 Jan 1970.
|
||||
-- `A_days' must represent a date that is not BC
|
||||
do
|
||||
set (1970, 1, 1)
|
||||
add_days (a_days)
|
||||
end
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
d, m, y: INTEGER
|
||||
do
|
||||
y := a_string.substring (1, 4).to_integer
|
||||
m := a_string.substring (5, 6).to_integer
|
||||
d := a_string.substring (7, 8).to_integer
|
||||
set (y, m, d)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Set the current object to today's date.
|
||||
-- This was copied from ISE's DATE class with the one minor change.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- This was copied from ISE's DATE class with the one minor change.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Set the current object to today's date in utc format.
|
||||
-- This was copied from ISE's TIME class with minor changes.
|
||||
do
|
||||
C_date.update
|
||||
set (C_date.year_now, C_date.month_now, C_date.day_now)
|
||||
end
|
||||
|
||||
set (a_year, a_month, a_day: INTEGER)
|
||||
-- Give date new year, month, and day.
|
||||
-- If day > num days in month then day will return last day in the month.
|
||||
require
|
||||
realistic_year: a_year /= 0
|
||||
realistic_month: a_month >= 1 and a_month <= 12
|
||||
realistic_day: a_day >= 1 and a_day <= 31
|
||||
do
|
||||
year := a_year
|
||||
month := a_month
|
||||
internal_day := a_day
|
||||
ensure
|
||||
year_assigned: year = a_year
|
||||
month_assigned: month = a_month
|
||||
day_assigned: day = a_day
|
||||
end
|
||||
|
||||
set_year (a_year: INTEGER)
|
||||
-- Change the year.
|
||||
require
|
||||
realistic_year: a_year /= 0
|
||||
do
|
||||
year := a_year
|
||||
ensure
|
||||
year_assigned: year = a_year
|
||||
end
|
||||
|
||||
set_month (a_month: INTEGER)
|
||||
-- Change the month.
|
||||
require
|
||||
realistic_month: a_month >= 1 and a_month <= 12
|
||||
do
|
||||
month := a_month
|
||||
ensure
|
||||
month_assigned: month = a_month
|
||||
end
|
||||
|
||||
set_day (a_day: INTEGER)
|
||||
-- Change the day.
|
||||
-- If a_day > number of days in the month then
|
||||
-- 'day' will be the last day of month.
|
||||
require
|
||||
realistic_day: a_day >= 1 and a_day <= 31
|
||||
do
|
||||
internal_day := a_day
|
||||
ensure
|
||||
day_assigned: day = a_day
|
||||
end
|
||||
|
||||
truncate_to_years
|
||||
-- Set the day to first day of month 1.
|
||||
-- Use when all but the `year' is to be ignored.
|
||||
do
|
||||
set_day (1)
|
||||
set_month (1)
|
||||
ensure
|
||||
year_unchanged: year = old year
|
||||
month_one: month = 1
|
||||
day_one: day = 1
|
||||
end
|
||||
|
||||
truncate_to_months
|
||||
-- Set day to first day of current month.
|
||||
-- Use when the `day' portion of date is to be ignored.
|
||||
do
|
||||
set_day (1)
|
||||
ensure
|
||||
year_unchanged: year = old year
|
||||
month_unchanged: month = old month
|
||||
day_one: day = 1
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_leapyear: BOOLEAN
|
||||
-- Is this a leapyear?
|
||||
do
|
||||
if is_bc then
|
||||
Result := (year + 1) \\ 4 = 0 and not ((year + 1) \\ 400 = 0)
|
||||
else
|
||||
Result := year \\ 4 = 0 and (not (year \\ 100 = 0) or else year \\ 400 = 0)
|
||||
end
|
||||
end
|
||||
|
||||
is_bc: BOOLEAN
|
||||
-- Does the date represent a date B.C. (ie year < 1)
|
||||
do
|
||||
Result := year <= -1
|
||||
ensure
|
||||
definition: Result implies year <= -1
|
||||
end
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
do
|
||||
Result := not is_bc and then
|
||||
(Current >= Minimum_representable_date and Current <= Maximum_representable_date)
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
days_between (other: like Current): INTEGER
|
||||
-- Days between this date and 'other'.
|
||||
-- Only works back to ~2 Mar 0001.
|
||||
require
|
||||
other_exists : other /= Void
|
||||
do
|
||||
Result := (other.internal - internal).abs
|
||||
ensure
|
||||
definition: Result = (other.internal - internal).abs
|
||||
end
|
||||
|
||||
time_between (other: like Current): like Duration_anchor
|
||||
-- The difference between two dates as a duration
|
||||
local
|
||||
larger, smaller: like Current
|
||||
y, m, d: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
y := larger.year - smaller.year
|
||||
m := larger.month - smaller.month
|
||||
d := larger.day - smaller.day
|
||||
if d < 0 then
|
||||
d := d + smaller.last_day_of_month
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 12
|
||||
y := y - 1
|
||||
end
|
||||
create Result
|
||||
Result.set (y, m, d)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
-- Dependent on the `internal' representation of dates.
|
||||
do
|
||||
-- These values were found by trial and error. This will give a
|
||||
-- date from 1 Jan 0001 to 18 Oct 1,469,902, which, I believe, is
|
||||
-- far enough into the future.
|
||||
Result := a_integer >= 1721426 and a_integer <= 538592032
|
||||
ensure then
|
||||
definition: Result implies (a_integer >= 1721426) and then
|
||||
(a_integer <= 538592032) -- dependent on `internal'
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
bcs: detachable STRING
|
||||
ys, ms, ds: STRING
|
||||
y, m, d: INTEGER
|
||||
pad: INTEGER -- add 2 if is "BC"
|
||||
do
|
||||
if a_string /= Void and then (a_string.count = 8 or a_string.count = 10) then
|
||||
if a_string.count = 10 then
|
||||
pad := 2
|
||||
bcs := a_string.substring (1, 2)
|
||||
end
|
||||
ys := a_string.substring (1 + pad, 4 + pad)
|
||||
ms := a_string.substring (5 + pad, 6 + pad)
|
||||
ds := a_string.substring (7 + pad, 8 + pad)
|
||||
if ys.is_integer and then ms.is_integer and then ds.is_integer then
|
||||
y := ys.to_integer
|
||||
m := ms.to_integer
|
||||
d := ds.to_integer
|
||||
if (y /= 0) and then (m >= 0 and m < 12)and then (d >= 0 and d <= 31) then
|
||||
Result := True
|
||||
if bcs /= Void and then not equal (bcs, "BC") then
|
||||
Result := False
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_years (a_num: INTEGER)
|
||||
-- Add 'a_num' number of years to the date. Works for negative numbers also.
|
||||
local
|
||||
y: INTEGER
|
||||
do
|
||||
y := year
|
||||
year := year + a_num
|
||||
if year = 0 then -- Must preserve invarient: year can not be 0.
|
||||
if y < 0 then -- year was less than 0 and increased to 0.
|
||||
year := 1
|
||||
else -- year was greater than 0 and decreased to 0.
|
||||
year := -1
|
||||
end
|
||||
end
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_months (a_num: INTEGER)
|
||||
-- Add 'a_num' number of months to the date. Works for negative numbers also.
|
||||
local
|
||||
m: INTEGER -- store month prior making month valid to call 'add_years'.
|
||||
do
|
||||
month := month + a_num
|
||||
m := month
|
||||
month := month \\ 12 -- preserve invarient
|
||||
if month < 1 then
|
||||
month := month + 12 -- preserve invarient
|
||||
add_years (-1)
|
||||
end
|
||||
add_years (m // 12) -- add a year for every multiple of 12.
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_days (a_num: INTEGER)
|
||||
-- Add 'a_num' number of days to the date. Works for negative numbers also.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
if a_num > 0 then
|
||||
from i := a_num
|
||||
until i <= days_remaining_this_month
|
||||
loop
|
||||
i := i - (days_remaining_this_month + 1)
|
||||
set_day (1)
|
||||
add_months (1)
|
||||
end
|
||||
set_day (day + i)
|
||||
elseif a_num < 0 then
|
||||
from
|
||||
i := a_num.abs
|
||||
until
|
||||
i < day
|
||||
loop
|
||||
i := (day - i).abs
|
||||
add_months (-1)
|
||||
set_day (last_day_of_month)
|
||||
end
|
||||
set_day (day - i)
|
||||
else
|
||||
-- do nothing if a_num = 0
|
||||
end
|
||||
ensure
|
||||
valid_date: is_valid
|
||||
end
|
||||
|
||||
add_duration (a_duration: like Duration_anchor)
|
||||
-- Add a length of time (in years, months, and days) to the date.
|
||||
do
|
||||
add_days (a_duration.days)
|
||||
add_months (a_duration.months)
|
||||
add_years (a_duration.years)
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this date come before 'other'?
|
||||
require else
|
||||
other_not_void: other /= Void
|
||||
do
|
||||
Result := year < other.year or else
|
||||
(year = other.year) and (month < other.month) or else
|
||||
(year = other.year) and (month = other.month) and (day < other.day)
|
||||
ensure then
|
||||
-- definition: year < other.year or else
|
||||
-- (year = other.year) and (month < other.month) or else
|
||||
-- (year = other.year) and (month = other.month) and (day < other.day)
|
||||
end
|
||||
|
||||
feature {YMD_TIME} -- Implementation
|
||||
|
||||
frozen internal: INTEGER
|
||||
-- Internal representation of YMD_TIME
|
||||
-- Used internally by some features.
|
||||
-- Does not work for BC dates; only works back to 1 January 0001,
|
||||
-- at which time the result is 1,721,426.
|
||||
-- Will work up to a date of 18 Oct 1,469,902 (found by trial).
|
||||
require
|
||||
not_bc: not is_bc
|
||||
local
|
||||
c, ya : INTEGER;
|
||||
d,m,y : INTEGER;
|
||||
do
|
||||
d := day;
|
||||
m := month;
|
||||
y := year;
|
||||
if m > 2 then
|
||||
m := m - 3;
|
||||
else
|
||||
m := m + 9;
|
||||
y := y - 1;
|
||||
end
|
||||
c := y // 100;
|
||||
ya := y - 100 * c;
|
||||
result := (146097 * c) // 4 + (1461 * ya) // 4 + (153 * m + 2) // 5 + d + 1721119;
|
||||
ensure
|
||||
result_large_enough: Result >= 1721426
|
||||
result_small_enough: Result <= 538592032
|
||||
end
|
||||
|
||||
frozen from_internal (num: INTEGER)
|
||||
-- Create a YMD_TIME from an internal representation.
|
||||
local
|
||||
y,m,d,j : INTEGER
|
||||
do
|
||||
j := num;
|
||||
j := j - 1721119
|
||||
y := (4 * j - 1) // 146097; j := 4 * j - 1 - 146097 * y;
|
||||
d := j // 4;
|
||||
j := (4 * d + 3) // 1461; d := 4 * d + 3 - 1461 * j;
|
||||
d := (d + 4) // 4;
|
||||
m := (5 * d - 3) // 153; d := 5 * d - 3 - 153 * m;
|
||||
d := (d + 5) // 5;
|
||||
y := 100 * y + j;
|
||||
if m < 10 then
|
||||
m := m + 3;
|
||||
else
|
||||
m := m - 9;
|
||||
y := y + 1;
|
||||
end;
|
||||
internal_day := d;
|
||||
month := m;
|
||||
year := y;
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
internal_day: INTEGER
|
||||
-- Used to save last day of month if day is greater than 28, 30, or 31.
|
||||
-- Actual day is calculated from this value.
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is the date logical?
|
||||
do
|
||||
Result := is_valid_year and is_valid_month and is_valid_day
|
||||
end
|
||||
|
||||
is_valid_year: BOOLEAN
|
||||
-- Is the year logical?
|
||||
-- Only invalid year is year "0".
|
||||
do
|
||||
Result := year /= 0
|
||||
ensure
|
||||
definition: year /= 0
|
||||
end
|
||||
|
||||
is_valid_month: BOOLEAN
|
||||
-- Is the month logical?
|
||||
do
|
||||
Result := 1 <= month and month <= 12
|
||||
ensure
|
||||
definition: 1 <= month and month <= 12
|
||||
end
|
||||
|
||||
is_valid_day: BOOLEAN
|
||||
-- Is the day logical based on month and year?
|
||||
do
|
||||
Result := day >= 1 and then
|
||||
( (day <= 28) or else
|
||||
((month=4 or month=6 or month=9 or month=11) and then day <= 30) or else
|
||||
((month=1 or month=3 or month=5 or month=7 or month=8 or month=10 or month=12) and then day <= 31) or else
|
||||
(month=2 and is_leapyear and day <= 29) )
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
Minimum_representable_date: like Current
|
||||
-- The earliest date that can be represented as an integer.
|
||||
-- This value is dependent on the implementation of `internal' and
|
||||
-- was found by trial and error to be 1 Jan 0001.
|
||||
do
|
||||
create Result
|
||||
Result.set_year (1)
|
||||
Result.set_month (1)
|
||||
Result.set_day (1)
|
||||
end
|
||||
|
||||
Maximum_representable_date: like Current
|
||||
-- The latest date that can be represented as an integer.
|
||||
-- This value is dependent on the implementation of `internal' and
|
||||
-- was found by trial and error to be 18 Oct 1,469,902.
|
||||
do
|
||||
create Result
|
||||
Result.set_year (1_469_902)
|
||||
Result.set_month (10)
|
||||
Result.set_day (18)
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: YMD_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
is_valid: is_valid
|
||||
|
||||
end -- class YMD_TIME
|
||||
|
||||
|
73
jj_temporal/jj_t/classes/ymd_timer.e
Normal file
73
jj_temporal/jj_t/classes/ymd_timer.e
Normal file
@ -0,0 +1,73 @@
|
||||
note
|
||||
description: "[
|
||||
Timer for hours, minutes, seconds, and miliseconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
|
||||
class
|
||||
YMD_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
YMD_INTERVAL
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {YMD_INTERVAL}
|
||||
Precursor {TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMD_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
268
jj_temporal/jj_t/classes/ymdhms_duration.e
Normal file
268
jj_temporal/jj_t/classes/ymdhms_duration.e
Normal file
@ -0,0 +1,268 @@
|
||||
note
|
||||
description: "[
|
||||
Duration of time described in years, months, days,
|
||||
hours, minutes, and seconds.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION
|
||||
|
||||
inherit
|
||||
|
||||
YMD_DURATION
|
||||
rename
|
||||
set as ymd_set,
|
||||
as_string as as_ymd_string
|
||||
redefine
|
||||
default_create,
|
||||
zero, one,
|
||||
set_zero,
|
||||
as_years, as_months, as_days,
|
||||
add, sub, multiply, divide, div, mod, negate, percent_of,
|
||||
is_less,
|
||||
normalize
|
||||
end
|
||||
|
||||
HMS_DURATION
|
||||
rename
|
||||
set as hms_set,
|
||||
as_string as as_hms_string
|
||||
redefine
|
||||
default_create,
|
||||
zero, one,
|
||||
set_zero,
|
||||
as_hours, as_minutes, as_seconds,
|
||||
add, sub, multiply, divide, div, mod, negate, percent_of,
|
||||
is_less,
|
||||
normalize
|
||||
select
|
||||
as_hms_string
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
Precursor {YMD_DURATION}
|
||||
Precursor {HMS_DURATION}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING_8
|
||||
-- The time represented as a string.
|
||||
do
|
||||
Result := as_ymd_string + ":" + as_hms_string
|
||||
end
|
||||
|
||||
zero: like Current
|
||||
-- Neutral element for "+" and "-"
|
||||
do
|
||||
create Result
|
||||
end
|
||||
|
||||
one: like Current
|
||||
-- Neutral element for "*" and "/"
|
||||
do
|
||||
create Result
|
||||
Result.set (1,1,1,1,1,1)
|
||||
end
|
||||
|
||||
as_years: DOUBLE
|
||||
-- Length of duration in years.
|
||||
do
|
||||
Result := years + months / 12 + days / days_per_year +
|
||||
hours / (24 * days_per_year) + minutes / (60 * 24 * days_per_year) +
|
||||
seconds / (60 * 60 * 24 * days_per_year)
|
||||
end
|
||||
|
||||
as_months: DOUBLE
|
||||
-- Length of duration in months.
|
||||
do
|
||||
Result := years * 12 + months + days / days_per_month +
|
||||
hours / hours_per_month + minutes / (60 * hours_per_month) +
|
||||
seconds / (60 * 60 * hours_per_month)
|
||||
end
|
||||
|
||||
as_days: DOUBLE
|
||||
-- Length of duration in days.
|
||||
do
|
||||
Result := years * days_per_year + months * days_per_month + days +
|
||||
hours / 24 + minutes / (24 * 60) + seconds / (24 * 60 * 60)
|
||||
end
|
||||
|
||||
as_hours: DOUBLE
|
||||
-- Length of this duration in hours.
|
||||
do
|
||||
Result := (years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours + minutes / 60 + seconds / 3600
|
||||
end
|
||||
|
||||
as_minutes: DOUBLE
|
||||
-- Length of this duration in minutes.
|
||||
do
|
||||
Result := ((years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours) -- number of hours
|
||||
* 60 + minutes + seconds / 60
|
||||
end
|
||||
|
||||
as_seconds: DOUBLE
|
||||
-- Length of this duration in seconds.
|
||||
do
|
||||
Result := (((years * days_per_year + months * days_per_month + days) -- number of days
|
||||
* 24 + hours) -- number of hours
|
||||
* 60 + minutes) -- number of minutes
|
||||
* 60 + seconds
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set (a_year, a_month, a_day, a_hour, a_minute, a_second: INTEGER)
|
||||
-- Change years, months, days, hours, minutes, seconds.
|
||||
do
|
||||
ymd_set (a_year, a_month, a_day)
|
||||
hms_set (a_hour, a_minute, a_second)
|
||||
ensure
|
||||
years_set: years = a_year
|
||||
months_set: months = a_month
|
||||
days_set: days = a_day
|
||||
hours_set: hours = a_hour
|
||||
minutes_set: minutes = a_minute
|
||||
seconds_set: seconds = a_second
|
||||
end
|
||||
|
||||
set_zero
|
||||
-- Make the duration be zero length.
|
||||
do
|
||||
ymd_set (0, 0, 0)
|
||||
set_fine (0, 0, 0, 0)
|
||||
end
|
||||
|
||||
|
||||
negate
|
||||
-- Reverse the sign for years, ..., seconds.
|
||||
do
|
||||
Precursor {YMD_DURATION}
|
||||
Precursor {HMS_DURATION}
|
||||
end
|
||||
|
||||
normalize
|
||||
-- Convert to standard format: "13 months" becomes "1 year, 1 month".
|
||||
-- Month and year length is based on 'days_per_month'.
|
||||
do
|
||||
Precursor {HMS_DURATION}
|
||||
set_days (days + hours // 24)
|
||||
set_hours (hours \\ 24)
|
||||
Precursor {YMD_DURATION}
|
||||
end
|
||||
|
||||
add (other: like Current)
|
||||
-- Add other to current.
|
||||
do
|
||||
Precursor {YMD_DURATION} (other)
|
||||
Precursor {HMS_DURATION} (other)
|
||||
end
|
||||
|
||||
sub (other: like Current)
|
||||
-- Subtract other from current.
|
||||
do
|
||||
Precursor {YMD_DURATION} (other)
|
||||
Precursor {HMS_DURATION} (other)
|
||||
end
|
||||
|
||||
multiply (r: DOUBLE)
|
||||
-- Multiply by a factor of 'r'.
|
||||
-- Result is normalized.
|
||||
local
|
||||
v: DOUBLE
|
||||
fract: DOUBLE
|
||||
do
|
||||
v := years * r
|
||||
years := v.floor
|
||||
fract := v - years
|
||||
|
||||
v := months * r + 12 * fract
|
||||
months := v.floor
|
||||
fract := v - months
|
||||
|
||||
v := days * r + days_per_month * fract
|
||||
days := v.floor
|
||||
fract := v - days
|
||||
|
||||
v := hours * r + 24 * fract
|
||||
hours := v.floor
|
||||
fract := v - hours
|
||||
|
||||
v := minutes * r + 60 * fract
|
||||
minutes := v.floor
|
||||
fract := v - minutes
|
||||
|
||||
v := seconds * r + 60 * fract
|
||||
seconds := v.rounded
|
||||
normalize
|
||||
end
|
||||
|
||||
divide (r: DOUBLE)
|
||||
-- Divide by 'r'.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (r) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
div (i: INTEGER)
|
||||
-- Integer division.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (i) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
mod (i: INTEGER)
|
||||
-- Modulo.
|
||||
-- Result is normalized.
|
||||
do
|
||||
Precursor {HMS_DURATION} (i) -- calculates based on seconds.
|
||||
end
|
||||
|
||||
percent_of (other: like Current): DOUBLE
|
||||
-- What percent of other in length is this one?
|
||||
do
|
||||
Result := as_days / other.as_days -- Days seemed reasonable accuracy.
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is this duration shorter than other?
|
||||
do
|
||||
Result := Precursor {YMD_DURATION} (other) or else
|
||||
(years = other.years and then months = other.months and then days = other.days and then
|
||||
Precursor {HMS_DURATION} (other))
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
hours_per_year: DOUBLE
|
||||
-- Number of hours in a year.
|
||||
do
|
||||
Result := days_per_year * 24
|
||||
end
|
||||
|
||||
hours_per_month: DOUBLE
|
||||
-- Number of hours in a month.
|
||||
do
|
||||
Result := days_per_month * 24
|
||||
end
|
||||
|
||||
|
||||
|
||||
end -- class YMDHMS_DURATION
|
||||
|
66
jj_temporal/jj_t/classes/ymdhms_duration_constants.e
Normal file
66
jj_temporal/jj_t/classes/ymdhms_duration_constants.e
Normal file
@ -0,0 +1,66 @@
|
||||
note
|
||||
description: "[
|
||||
Constants for use with {YMDHMS_TIME}, {YMDHMS_DURATION},
|
||||
and {YMDHMS_INTERVAL}.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION_CONSTANTS
|
||||
|
||||
feature -- Access
|
||||
|
||||
One_second: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 0, 0, 1)
|
||||
end
|
||||
|
||||
One_minute: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 0, 1, 0)
|
||||
end
|
||||
|
||||
One_hour: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 0, 1, 0, 0)
|
||||
end
|
||||
|
||||
One_day: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 1, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_week: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 0, 7, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_month: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 1, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_quarter: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (0, 3, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
One_year: YMDHMS_DURATION
|
||||
once
|
||||
create Result
|
||||
Result.set (1, 0, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
end -- class YMDHMS_DURATION_CONSTANTS
|
60
jj_temporal/jj_t/classes/ymdhms_interval.e
Normal file
60
jj_temporal/jj_t/classes/ymdhms_interval.e
Normal file
@ -0,0 +1,60 @@
|
||||
note
|
||||
description: "[
|
||||
A span of time consisting of a start-time, finish-time
|
||||
and duration described in terms of years, months,
|
||||
days, hours, minutes, and seconds. Positive durations only.
|
||||
]"
|
||||
names: "ymdhms_interval, interval, time_span, time_interval, span"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_INTERVAL
|
||||
|
||||
inherit
|
||||
|
||||
HMS_INTERVAL
|
||||
undefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
YMD_INTERVAL
|
||||
redefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
391
jj_temporal/jj_t/classes/ymdhms_time.e
Normal file
391
jj_temporal/jj_t/classes/ymdhms_time.e
Normal file
@ -0,0 +1,391 @@
|
||||
note
|
||||
description: "[
|
||||
An exact point of time of a particular day. A Year, Month, Day,
|
||||
Hour, Minute, Second - time (ie. a date and time).
|
||||
]"
|
||||
names: "date, time, date_and_time"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_TIME
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME
|
||||
rename
|
||||
set as set_ymd_time,
|
||||
as_days as as_seconds,
|
||||
from_days as from_seconds
|
||||
redefine
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_utc_fine,
|
||||
is_less,
|
||||
is_valid,
|
||||
add_duration,
|
||||
time_between,
|
||||
-- normalize,
|
||||
truncate_to_years,
|
||||
truncate_to_months,
|
||||
as_string,
|
||||
as_seconds,
|
||||
from_seconds,
|
||||
from_string,
|
||||
is_valid_string_representation,
|
||||
is_valid_integer_representation,
|
||||
is_representable_as_integer,
|
||||
duration_anchor,
|
||||
interval_anchor
|
||||
end
|
||||
|
||||
HMS_TIME
|
||||
rename
|
||||
set as set_hms_time
|
||||
redefine
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
is_less,
|
||||
is_valid,
|
||||
add_duration,
|
||||
time_between,
|
||||
seconds_between,
|
||||
add_hours,
|
||||
-- normalize,
|
||||
truncate_to_hours,
|
||||
truncate_to_minutes,
|
||||
as_string,
|
||||
as_seconds,
|
||||
from_seconds,
|
||||
from_string,
|
||||
is_valid_string_representation,
|
||||
is_valid_integer_representation,
|
||||
is_representable_as_integer,
|
||||
Duration_anchor,
|
||||
Interval_anchor
|
||||
select
|
||||
from_seconds
|
||||
end
|
||||
|
||||
create
|
||||
default_create,
|
||||
set_now,
|
||||
set_now_utc,
|
||||
set_now_fine,
|
||||
set_now_utc_fine,
|
||||
from_seconds,
|
||||
from_string
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance with todays date at midnight.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
as_string: STRING
|
||||
-- String representation of Current in a compact form.
|
||||
do
|
||||
Result := Precursor {YMD_TIME}
|
||||
Result.append ("T")
|
||||
Result.append (Precursor {HMS_TIME})
|
||||
end
|
||||
|
||||
as_seconds: INTEGER
|
||||
-- The number of seconds from midnight (00:00:00)
|
||||
-- on 1 Jan 1970 to the Current time.
|
||||
local
|
||||
days: INTEGER
|
||||
do
|
||||
days := Precursor {YMD_TIME}
|
||||
Result := days * 24 * 60 * 60 + Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
from_string (a_string: STRING)
|
||||
-- Change Current to the time represented by `a_string'.
|
||||
-- It must be in the format as provided by `as_string'.
|
||||
local
|
||||
pos: INTEGER
|
||||
do
|
||||
pos := a_string.index_of ('T', 1)
|
||||
Precursor {YMD_TIME} (a_string.substring (1, pos - 1))
|
||||
Precursor {HMS_TIME} (a_string.substring (pos + 1, a_string.count))
|
||||
end
|
||||
|
||||
from_seconds (a_seconds: INTEGER)
|
||||
-- Change Current to the time represented by `a_seconds'.
|
||||
-- `A_seconds' is assumed to be the number of seconds since 1 Jan 1970.
|
||||
-- It must represent a date that is not BC.
|
||||
do
|
||||
set (1970, 1, 1, 0, 0, 0)
|
||||
add_seconds (a_seconds)
|
||||
end
|
||||
|
||||
set_now
|
||||
-- Initialize the instance from the system clock unsing the
|
||||
-- current time zone.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
set_now_utc
|
||||
-- Initialize the instance from the system clock unsing GMT.
|
||||
do
|
||||
Precursor {HMS_TIME}
|
||||
Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
set_now_fine
|
||||
-- Initialize the instance from the system clock using the current
|
||||
-- time zone and including milliseconds.
|
||||
do
|
||||
set_now
|
||||
Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
set_now_utc_fine
|
||||
-- Initialize the instance from the system clock using the GMT and
|
||||
-- including milliseconds.
|
||||
do
|
||||
set_now_utc
|
||||
Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
set (a_year, a_month, a_day, a_hour, a_minute, a_second: INTEGER)
|
||||
-- Change the 'year', ..., 'second'.
|
||||
require
|
||||
year_valid: a_year /= 0;
|
||||
month_valid: 1 <= a_month and a_month <= 12;
|
||||
day_valid: 1 <= a_day and a_day <= 31;
|
||||
hour_valid: 0 <= a_hour and a_hour <= 23;
|
||||
minute_valid: 0 <= a_minute and a_minute <= 59;
|
||||
second_valid: 0 <= a_second and a_second <= 59
|
||||
do
|
||||
set_ymd_time (a_year, a_month, a_day);
|
||||
set_hms_time (a_hour, a_minute, a_second);
|
||||
end
|
||||
|
||||
truncate_to_years
|
||||
-- Set to midnight on the first day of month 1.
|
||||
-- Use when all but the `year' is to be ignored.
|
||||
do
|
||||
Precursor {YMD_TIME}
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_one: month = 1
|
||||
day_one: day = 1
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_months
|
||||
-- Set to midnight on the first day of the current month.
|
||||
-- Use when all but the `year' and `month' is to be ignored.
|
||||
do
|
||||
Precursor {YMD_TIME}
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_unchaged: month = old month
|
||||
day_one: day = 1
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_days
|
||||
-- Set to midnight on the current day.
|
||||
-- Use when the time portion of the date is to be ignored.
|
||||
do
|
||||
set_hms_time (0, 0, 0)
|
||||
ensure then
|
||||
year_unchanged: year = old year
|
||||
month_unchaged: month = old month
|
||||
day_unchaged: day = old day
|
||||
hour_zero: hour = 0
|
||||
minute_zero: minute = 0
|
||||
second_zero: second = 0
|
||||
end
|
||||
|
||||
truncate_to_hours
|
||||
-- Set the `hour', `second', and `millisecond' to zero.
|
||||
-- Used when these portions of the time are to be ignored.
|
||||
do
|
||||
set (year, month, day, hour, 0, 0)
|
||||
end
|
||||
|
||||
truncate_to_minutes
|
||||
do
|
||||
set (year, month, day, hour, minute, 0)
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
add_duration (a_duration: like duration_anchor)
|
||||
-- Add a length of time (in years, months, days,
|
||||
-- hours, minutes, and seconds) to the time.
|
||||
do
|
||||
Precursor {HMS_TIME} (a_duration)
|
||||
add_days (overflow)
|
||||
clear_overflow
|
||||
Precursor {YMD_TIME} (a_duration)
|
||||
ensure then
|
||||
no_overflowing_days: overflow = 0
|
||||
end
|
||||
|
||||
add_hours (a_number: INTEGER)
|
||||
-- Add `a_number' of hours to the current time
|
||||
do
|
||||
Precursor {HMS_TIME} (a_number)
|
||||
add_days (overflow)
|
||||
clear_overflow
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_representable_as_integer: BOOLEAN
|
||||
-- Can Current be represented as an integer?
|
||||
do
|
||||
Result := Precursor {HMS_TIME} and then Precursor {YMD_TIME}
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
time_between (other: like Current): like duration_anchor
|
||||
-- The difference between two dates as a time span or duration.
|
||||
local
|
||||
larger, smaller: like Current
|
||||
y, mon, d, h, m, s: INTEGER
|
||||
do
|
||||
larger := max (other)
|
||||
smaller := min (other)
|
||||
y := larger.year - smaller.year
|
||||
mon := larger.month - smaller.month
|
||||
d := larger.day - smaller.day
|
||||
h := larger.hour - smaller.hour
|
||||
m := larger.minute - smaller.minute
|
||||
s := larger.second - smaller.second
|
||||
if s < 0 then
|
||||
s := s + 60
|
||||
m := m - 1
|
||||
end
|
||||
if m < 0 then
|
||||
m := m + 60
|
||||
h := h - 1
|
||||
end
|
||||
if h < 0 then
|
||||
h := h + 24
|
||||
d := d - 1
|
||||
end
|
||||
if d < 0 then
|
||||
d := d + smaller.last_day_of_month
|
||||
mon := mon - 1
|
||||
end
|
||||
if mon < 0 then
|
||||
mon := mon + 12
|
||||
y := y - 1
|
||||
end
|
||||
create Result
|
||||
Result.set (y, mon, d, h, m, s)
|
||||
if Current < other then
|
||||
Result.negate
|
||||
end
|
||||
end
|
||||
|
||||
seconds_between (a_other: like Current): INTEGER
|
||||
-- The number of seconds between Current and `a_other'.
|
||||
do
|
||||
Result := days_between (a_other) * 24 * 60 * 60 + Precursor {HMS_TIME} (a_other)
|
||||
end
|
||||
|
||||
is_valid_string_representation (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' in a format that can be used to initialize Current?
|
||||
local
|
||||
i: INTEGER
|
||||
ds, ts: STRING
|
||||
do
|
||||
if a_string /= Void then
|
||||
i := a_string.index_of ('T', 1)
|
||||
ds := a_string.substring (1, i - 1)
|
||||
ts := a_string.substring (i + 1, a_string.count)
|
||||
Result := Precursor {YMD_TIME} (ds) and then Precursor {HMS_TIME} (ts)
|
||||
end
|
||||
end
|
||||
|
||||
is_valid_integer_representation (a_integer: INTEGER): BOOLEAN
|
||||
-- Is `a_integer' in range to be converted to a time?
|
||||
do
|
||||
Result := Precursor {HMS_TIME} (a_integer) and then
|
||||
Precursor {YMD_TIME} (a_integer)
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Does this date_and_time come before 'other'
|
||||
do
|
||||
Result := year < other.year or else
|
||||
((year = other.year) and (month < other.month)) or else
|
||||
((year = other.year) and (month = other.month) and (day < other.day)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour < other.hour)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute < other.minute)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute = other.minute) and (second < other.second)) or else
|
||||
((year = other.year) and (month = other.month) and (day = other.day) and
|
||||
(hour = other.hour) and (minute = other.minute) and (second = other.second) and
|
||||
(millisecond < other.millisecond))
|
||||
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
is_valid: BOOLEAN
|
||||
-- Is the date and time logical?
|
||||
do
|
||||
Result := Precursor {YMD_TIME} and Precursor {HMS_TIME}
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
interval_anchor: YMDHMS_INTERVAL
|
||||
-- Anchor for features using intervals.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
end
|
77
jj_temporal/jj_t/classes/ymdhms_timer.e
Normal file
77
jj_temporal/jj_t/classes/ymdhms_timer.e
Normal file
@ -0,0 +1,77 @@
|
||||
note
|
||||
description: "Summary description for {YMDHMS_TIMER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
YMDHMS_TIMER
|
||||
|
||||
inherit
|
||||
|
||||
YMDHMS_INTERVAL
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
HMS_TIMER
|
||||
undefine
|
||||
duration
|
||||
redefine
|
||||
default_create,
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
end
|
||||
|
||||
YMD_TIMER
|
||||
undefine
|
||||
time_anchor,
|
||||
duration_anchor
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
-- Set up the timer
|
||||
do
|
||||
Precursor {YMDHMS_INTERVAL}
|
||||
Precursor {YMD_TIMER}
|
||||
create cumulative
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Anchor for features using times.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
duration_anchor: YMDHMS_DURATION
|
||||
-- Anchor for features using durations.
|
||||
-- Not to be called; just used to anchor types.
|
||||
-- Declared as a feature to avoid adding an attribute.
|
||||
once
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because give no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
88
jj_temporal/jj_t/demo/jj_temporal_demo.e
Normal file
88
jj_temporal/jj_t/demo/jj_temporal_demo.e
Normal file
@ -0,0 +1,88 @@
|
||||
note
|
||||
description: "[
|
||||
Test objects for temporal cluster.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL: $"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
|
||||
class
|
||||
JJ_TEMPORAL_DEMO
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create date
|
||||
create time
|
||||
create date_time
|
||||
io.put_string (date.out)
|
||||
io.new_line
|
||||
io.new_line
|
||||
io.put_string (time.out)
|
||||
io.new_line
|
||||
io.new_line
|
||||
io.put_string (date_time.out)
|
||||
|
||||
create ymd_formatter
|
||||
create timer_1
|
||||
create timer_2
|
||||
timer_1.reset
|
||||
timer_2.reset
|
||||
|
||||
from i := 1
|
||||
until i > 10
|
||||
loop
|
||||
io.put_string ("i = " + i.out + "%N")
|
||||
timer_1.run
|
||||
ee.sleep (100)
|
||||
timer_1.stop
|
||||
timer_2.run
|
||||
ee.sleep (1_000_000_000)
|
||||
timer_2.stop
|
||||
io.put_string ("timer_1.cumulative = " + timer_1.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
io.put_string ("timer_2.cumulative = " + timer_2.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
i := i + 1
|
||||
end
|
||||
io.put_string ("timer_1.cumulative = " + timer_1.cumulative.as_seconds.out)
|
||||
io.put_string (" %T")
|
||||
io.put_string ("timer_2.cumulative = " + timer_2.cumulative.as_seconds.out)
|
||||
io.new_line
|
||||
|
||||
-- io.put_string ("The formatted date = ")
|
||||
-- io.put_string (ymd_formatter.to_string (date) + "%N")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
date: YMD_TIME
|
||||
-- To test a date
|
||||
|
||||
time: HMS_TIME
|
||||
-- To test a time
|
||||
|
||||
date_time: YMDHMS_TIME
|
||||
-- To test a date and time
|
||||
|
||||
ymd_formatter: YMD_TIME_FORMATTER
|
||||
-- To test the gobo parsers
|
||||
|
||||
timer_1, timer_2: HMS_TIMER
|
||||
|
||||
ee: EXECUTION_ENVIRONMENT
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
end
|
23
jj_temporal/jj_t/demo/jj_temporal_demo.ecf
Normal file
23
jj_temporal/jj_t/demo/jj_temporal_demo.ecf
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="jj_temporal_demo" uuid="E55510BE-486F-4ED3-A6C5-1FCCECA93777">
|
||||
<target name="jj_temporal_demo">
|
||||
<root class="JJ_TEMPORAL_DEMO" feature="make"/>
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" is_obsolete_routine_type="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="jj_temporal" location="..\jj_temporal.ecf" readonly="false">
|
||||
<option is_obsolete_routine_type="true">
|
||||
<assertions precondition="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<cluster name="demo" location=".\">
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
18
jj_temporal/jj_t/docs/Forum.txt
Normal file
18
jj_temporal/jj_t/docs/Forum.txt
Normal file
@ -0,0 +1,18 @@
|
||||
Eiffel Forum License, version 2
|
||||
|
||||
1. Permission is hereby granted to use, copy, modify and/or
|
||||
distribute this package, provided that:
|
||||
* copyright notices are retained unchanged,
|
||||
* any distribution of this package, whether modified or not,
|
||||
includes this license text.
|
||||
2. Permission is hereby also granted to distribute binary programs
|
||||
which depend on this package. If the binary program depends on a
|
||||
modified version of this package, you are encouraged to publicly
|
||||
release the modified version of this package.
|
||||
|
||||
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THIS PACKAGE.
|
BIN
jj_temporal/jj_t/docs/main_classes.png
Normal file
BIN
jj_temporal/jj_t/docs/main_classes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
192
jj_temporal/jj_t/formatters/hms_duration_formatter.e
Normal file
192
jj_temporal/jj_t/formatters/hms_duration_formatter.e
Normal file
@ -0,0 +1,192 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {HMS_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_hms_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
date: "18 Feb 03"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (", ")
|
||||
set_hour_minute_second
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_hour_minute_second
|
||||
-- Set format to day-month-year.
|
||||
do
|
||||
format := hms
|
||||
end
|
||||
|
||||
set_second_minute_hour
|
||||
do
|
||||
format := smh
|
||||
end
|
||||
|
||||
set_hour_minute
|
||||
do
|
||||
format := hm
|
||||
end
|
||||
|
||||
set_minute_hour
|
||||
do
|
||||
format := mh
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
hour_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make(8)
|
||||
Result.append_integer (a_duration.hours)
|
||||
Result.append (" hour")
|
||||
if a_duration.hours /= 1 and a_duration.hours /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
minute_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.minutes)
|
||||
Result.append (" minute")
|
||||
if a_duration.minutes /= 1 and a_duration.minutes /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
second_string (a_duration: HMS_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.seconds)
|
||||
Result.append (" second")
|
||||
if a_duration.seconds /= 1 and a_duration.seconds /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_duration: HMS_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (hour_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (minute_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (second_string(a_duration))
|
||||
end
|
||||
|
||||
string_to_duration (a_string: STRING): HMS_DURATION
|
||||
-- Parse the string based on the current formatting.
|
||||
require
|
||||
valid_date_string: is_valid_duration_string (a_string)
|
||||
do
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_duration_string (a_string: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
-- parse the string
|
||||
Result := True
|
||||
-- !!! temporary
|
||||
end
|
||||
|
||||
is_index_in_hour_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
date_exists: a_date /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ds := hour_string (a_date)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_minute_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ms := minute_string (a_date)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_second_string (a_date: HMS_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ys := second_string (a_date)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
format: INTEGER
|
||||
|
||||
hms, smh, -- hours-minutes-seconds, etc
|
||||
hm, mh : INTEGER = unique -- hours-minutes only
|
||||
|
||||
hms_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end -- class HMS_DURATION_FORMATTER
|
||||
|
||||
|
245
jj_temporal/jj_t/formatters/hms_time_formatter.e
Normal file
245
jj_temporal/jj_t/formatters/hms_time_formatter.e
Normal file
@ -0,0 +1,245 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {HMS_TIME}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `to_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_hms_time' is more
|
||||
relaxed.
|
||||
]"
|
||||
date: "18 Feb 03"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
HMS_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (":")
|
||||
hide_seconds
|
||||
set_12_hour
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
separator_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_12_hour
|
||||
do
|
||||
is_12_hour := True
|
||||
end
|
||||
|
||||
set_24_hour
|
||||
do
|
||||
is_12_hour := False
|
||||
end
|
||||
|
||||
show_seconds
|
||||
do
|
||||
is_seconds_shown := True
|
||||
end
|
||||
|
||||
hide_seconds
|
||||
do
|
||||
is_seconds_shown := False
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
hour_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
local
|
||||
h: INTEGER
|
||||
do
|
||||
h := a_time.hour
|
||||
if is_12_hour and then h >= 12 then
|
||||
h := h - 12
|
||||
end
|
||||
if is_12_hour and then h = 0 then
|
||||
h := 12
|
||||
end
|
||||
create Result.make(2)
|
||||
if h < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (h)
|
||||
end
|
||||
|
||||
minute_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make(2)
|
||||
if a_time.minute < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_time.minute)
|
||||
end
|
||||
|
||||
second_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make(2)
|
||||
if a_time.second < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_time.second)
|
||||
end
|
||||
|
||||
am_pm_string (a_time: like time_anchor): STRING
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make (3)
|
||||
if a_time.hour >= 12 then
|
||||
Result.append (" PM")
|
||||
else
|
||||
Result.append (" AM")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_time: like time_anchor): STRING
|
||||
-- the whole {HMS_TIME} as a string
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (hour_string (a_time))
|
||||
Result.append (separator)
|
||||
Result.append (minute_string (a_time))
|
||||
if is_seconds_shown then
|
||||
Result.append (separator)
|
||||
Result.append (second_string (a_time))
|
||||
end
|
||||
if is_12_hour then
|
||||
Result.append (am_pm_string (a_time))
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_12_hour: BOOLEAN
|
||||
|
||||
is_seconds_shown: BOOLEAN
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_time_string (a_time: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_time /= Void
|
||||
do
|
||||
-- parse the string
|
||||
end
|
||||
|
||||
is_index_in_hour_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, hs: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
hs := hour_string (a_time)
|
||||
i := s.substring_index (hs, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + hs.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_minute_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ms := minute_string (a_time)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_second_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ss: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ss := hour_string (a_time)
|
||||
i := s.substring_index (ss, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ss.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_am_pm_string (a_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
time_exists: a_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ss: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_time)
|
||||
ss := am_pm_string (a_time)
|
||||
i := s.substring_index (ss, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ss.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: HMS_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
hms_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
192
jj_temporal/jj_t/formatters/ymd_duration_formatter.e
Normal file
192
jj_temporal/jj_t/formatters/ymd_duration_formatter.e
Normal file
@ -0,0 +1,192 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMD_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a duration in feature `to_ymd_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
ANY
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
set_separator (", ")
|
||||
set_year_month_day
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
end
|
||||
|
||||
set_day_month_year
|
||||
-- Set format to day-month-year.
|
||||
do
|
||||
format := dmy
|
||||
end
|
||||
|
||||
set_year_month_day
|
||||
do
|
||||
format := ymd
|
||||
end
|
||||
|
||||
set_day_month
|
||||
do
|
||||
format := dm
|
||||
end
|
||||
|
||||
set_month_year
|
||||
do
|
||||
format := my
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
year_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make(8)
|
||||
Result.append_integer (a_duration.years)
|
||||
Result.append (" year")
|
||||
if a_duration.years /= 1 and a_duration.years /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
month_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.months)
|
||||
Result.append (" month")
|
||||
if a_duration.months /= 1 and a_duration.months /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
day_string (a_duration: YMD_DURATION): STRING
|
||||
do
|
||||
create Result.make (8)
|
||||
Result.append_integer (a_duration.days)
|
||||
Result.append (" day")
|
||||
if a_duration.days /= 1 and a_duration.days /= -1 then
|
||||
Result.append ("s")
|
||||
end
|
||||
end
|
||||
|
||||
to_string (a_duration: YMD_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
do
|
||||
create Result.make (20)
|
||||
Result.append (day_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (month_string(a_duration))
|
||||
Result.append (separator)
|
||||
Result.append (year_string(a_duration))
|
||||
end
|
||||
|
||||
string_to_duration (a_string: STRING): YMD_DURATION
|
||||
-- Parse the string based on the current formatting.
|
||||
require
|
||||
valid_date_string: is_valid_date_string (a_string)
|
||||
do
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid_date_string (a_string: STRING): BOOLEAN
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
-- parse the string
|
||||
Result := True
|
||||
-- !!! temporary
|
||||
end
|
||||
|
||||
is_index_in_day_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
date_exists: a_date /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ds := day_string (a_date)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_month_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ms := month_string (a_date)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_year_string (a_date: YMD_DURATION; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_date)
|
||||
ys := year_string (a_date)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
format: INTEGER
|
||||
|
||||
dmy, ymd, -- day-month-year, etc
|
||||
dm, my : INTEGER = unique -- day-month or month-year only
|
||||
|
||||
dmy_parse (a_string: STRING)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
end -- class YMD_DURATION_FORMATTER
|
||||
|
||||
|
133
jj_temporal/jj_t/formatters/ymd_time_format_constants.e
Normal file
133
jj_temporal/jj_t/formatters/ymd_time_format_constants.e
Normal file
@ -0,0 +1,133 @@
|
||||
note
|
||||
description: "[
|
||||
Constants describing how {YMD_TIME}'s (dates) should appear.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
|
||||
feature -- Assess
|
||||
|
||||
Day_month_year: INTEGER = 0
|
||||
-- (e.g. "31 January 2004" or "31/01/04")
|
||||
|
||||
Year_month_day: INTEGER = 1
|
||||
-- (e.g. "2004 January 31" or "04/01/31")
|
||||
|
||||
Month_day_year: INTEGER = 2
|
||||
-- (e.g. "January 31, 2004" or "01/31/04")
|
||||
|
||||
Day_month: INTEGER = 3
|
||||
-- (e.g. "31 January" or "31/01")
|
||||
|
||||
Month_year: INTEGER = 4
|
||||
-- (e.g. "January 2004" or "01/04")
|
||||
|
||||
days_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("SUN")
|
||||
Result.extend ("MON")
|
||||
Result.extend ("TUE")
|
||||
Result.extend ("WED")
|
||||
Result.extend ("THU")
|
||||
Result.extend ("FRI")
|
||||
Result.extend ("SAT")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
months_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("JAN")
|
||||
Result.extend ("FEB")
|
||||
Result.extend ("MAR")
|
||||
Result.extend ("APR")
|
||||
Result.extend ("MAY")
|
||||
Result.extend ("JUN")
|
||||
Result.extend ("JUL")
|
||||
Result.extend ("AUG")
|
||||
Result.extend ("SEP")
|
||||
Result.extend ("OCT")
|
||||
Result.extend ("NOV")
|
||||
Result.extend ("DEC")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
long_days_text: LINKED_LIST [STRING]
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("SUNDAY")
|
||||
Result.extend ("MONDAY")
|
||||
Result.extend ("TUESDAY")
|
||||
Result.extend ("WEDNESDAY")
|
||||
Result.extend ("THURSDAY")
|
||||
Result.extend ("FRIDAY")
|
||||
Result.extend ("SATURDAY")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
long_months_text: LINKED_LIST [STRING]
|
||||
--
|
||||
once
|
||||
create Result.make
|
||||
Result.extend ("JANUARY")
|
||||
Result.extend ("FEBRUARY")
|
||||
Result.extend ("MARCH")
|
||||
Result.extend ("APRIL")
|
||||
Result.extend ("MAY")
|
||||
Result.extend ("JUNE")
|
||||
Result.extend ("JULY")
|
||||
Result.extend ("AUGUST")
|
||||
Result.extend ("SEPTEMBER")
|
||||
Result.extend ("OCTOBER")
|
||||
Result.extend ("NOVEMBER")
|
||||
Result.extend ("DECEMBER")
|
||||
Result.compare_objects
|
||||
end
|
||||
|
||||
feature -- Querry
|
||||
|
||||
is_valid_format (a_integer: INTEGER): BOOLEAN
|
||||
-- Does `a_integer' represent a valid date format?
|
||||
do
|
||||
Result := a_integer = Day_month_year or else
|
||||
a_integer = Year_month_day or else
|
||||
a_integer = Month_day_year or else
|
||||
a_integer = Day_month or else
|
||||
a_integer = Month_year
|
||||
end
|
||||
|
||||
is_month (a_string: STRING): BOOLEAN
|
||||
-- Does a_string represent a month?
|
||||
do
|
||||
Result := months_text.has (a_string.as_upper) or else
|
||||
long_months_text.has (a_string.as_upper)
|
||||
end
|
||||
|
||||
is_weekday (a_string: STRING): BOOLEAN
|
||||
-- Does `a_string' represent a weekday?
|
||||
do
|
||||
Result := days_text.has (a_string.as_upper) or else
|
||||
long_days_text.has (a_string.as_upper)
|
||||
end
|
||||
|
||||
get_month (a_month: STRING): INTEGER
|
||||
-- Number of the `a_month'
|
||||
require
|
||||
is_month: is_month (a_month)
|
||||
do
|
||||
if months_text.has (a_month.as_upper) then
|
||||
Result := months_text.index_of (a_month.as_upper, 1)
|
||||
else
|
||||
Result := long_months_text.index_of (a_month.as_upper, 1)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
397
jj_temporal/jj_t/formatters/ymd_time_formatter.e
Normal file
397
jj_temporal/jj_t/formatters/ymd_time_formatter.e
Normal file
@ -0,0 +1,397 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMD_TIME}'s (i.e. dates) to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymd_time' is more relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
-- Create an instance to parse dates in "dd mmm yy" format.
|
||||
do
|
||||
set_separator (" ")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
separator: STRING
|
||||
-- The character (or string) placed between the day, month, year, etc.
|
||||
|
||||
to_ymd_time (a_string: STRING): like time_anchor
|
||||
-- Parse `a_string'
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
is_string_valid: is_valid (a_string)
|
||||
do
|
||||
Result := parsed (a_string)
|
||||
ensure
|
||||
result_exists: Result /= Void
|
||||
end
|
||||
|
||||
to_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The complete string representation of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (20)
|
||||
inspect format
|
||||
when Day_month_year then
|
||||
if is_weekday_included then
|
||||
Result.append (weekday_string (a_ymd_time))
|
||||
Result.append (", ")
|
||||
end
|
||||
Result.append (day_string (a_ymd_time))
|
||||
Result.append (separator)
|
||||
Result.append (month_string (a_ymd_time))
|
||||
Result.append (separator)
|
||||
Result.append (year_string (a_ymd_time))
|
||||
when Year_month_day then
|
||||
when Month_day_year then
|
||||
when Month_year then
|
||||
when Day_month then
|
||||
else
|
||||
check
|
||||
should_not_happen: False
|
||||
-- because format must be one of these
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
year_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `year' feature of `a_ymd_time'.
|
||||
-- Will be shortened to two characters if `is_short_format'.
|
||||
do
|
||||
create Result.make(4)
|
||||
Result.append_integer (a_ymd_time.year)
|
||||
if is_short_format then
|
||||
if a_ymd_time.year < 10 then
|
||||
Result.keep_tail (1)
|
||||
if is_zero_padded then
|
||||
Result.prepend ("0")
|
||||
end
|
||||
else
|
||||
Result.keep_tail (2)
|
||||
end
|
||||
else
|
||||
if is_zero_padded then
|
||||
if a_ymd_time.year < 10 then
|
||||
Result.prepend ("000")
|
||||
elseif a_ymd_time.year < 100 then
|
||||
Result.prepend ("00")
|
||||
elseif a_ymd_time.year < 1000 then
|
||||
Result.prepend ("0")
|
||||
end
|
||||
end
|
||||
end
|
||||
ensure
|
||||
valid_length_if_short: is_short_format implies Result.count <= 2
|
||||
end
|
||||
|
||||
month_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `month' feature of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (10)
|
||||
if is_month_numeric then
|
||||
if is_zero_padded and a_ymd_time.month < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_ymd_time.month)
|
||||
else
|
||||
if is_short_format then
|
||||
Result.append (months_text.i_th (a_ymd_time.month))
|
||||
else
|
||||
Result.append (long_months_text.i_th (a_ymd_time.month))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
day_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string representation of `day' feature of `a_ymd_time'.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (2)
|
||||
if is_zero_padded and a_ymd_time.day < 10 then
|
||||
Result.append ("0")
|
||||
end
|
||||
Result.append_integer (a_ymd_time.day)
|
||||
end
|
||||
|
||||
weekday_string (a_ymd_time: like time_anchor): STRING
|
||||
-- The string repesentation of the `weekday' of `a_ymd_time'.
|
||||
-- (i.e. "Sunday", "Monday, etc. or "Sun", "Mon", etc.
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
do
|
||||
create Result.make (15)
|
||||
inspect a_ymd_time.weekday
|
||||
when 1 then Result.append ("Sunday")
|
||||
when 2 then Result.append ("Monday")
|
||||
when 3 then Result.append ("Tuesday")
|
||||
when 4 then Result.append ("Wednesday")
|
||||
when 5 then Result.append ("Thursday")
|
||||
when 6 then Result.append ("Friday")
|
||||
when 7 then Result.append ("Saturday")
|
||||
else
|
||||
check
|
||||
should_not_happen: False
|
||||
-- because `weekday' ranges from 1 to 7.
|
||||
end
|
||||
end
|
||||
if is_short_format then
|
||||
Result.keep_head (3)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_separator (a_string: STRING)
|
||||
-- Set `separator' to `a_string'.
|
||||
require
|
||||
separator_exists: a_string /= Void
|
||||
do
|
||||
separator := a_string
|
||||
ensure
|
||||
seperator_set: separator = a_string
|
||||
end
|
||||
|
||||
set_format (a_format: INTEGER)
|
||||
-- Change `format'.
|
||||
-- The values are in YMD_TIME_FORMAT_CONSTANTS
|
||||
require
|
||||
valid_format: is_valid_format (a_format)
|
||||
do
|
||||
format := a_format
|
||||
end
|
||||
|
||||
set_show_weekday
|
||||
-- Include the day of the week in the output string.
|
||||
do
|
||||
is_weekday_included := True
|
||||
end
|
||||
|
||||
set_hide_weekday
|
||||
-- Do not include the day of the week in the output string.
|
||||
do
|
||||
is_weekday_included := False
|
||||
end
|
||||
|
||||
set_format_short
|
||||
-- Abriviate the `month_string' (if shown as text) to three
|
||||
-- characters and shorten the year to two digits.
|
||||
do
|
||||
is_short_format := True
|
||||
end
|
||||
|
||||
set_format_long
|
||||
-- Show the `month_string' (if shown as text) to the complete
|
||||
-- (unabriviated) word and show the year as four digits.
|
||||
do
|
||||
is_short_format := False
|
||||
end
|
||||
|
||||
set_month_numeric
|
||||
-- Make the month appear as digits, not text.
|
||||
do
|
||||
is_month_numeric := True
|
||||
ensure
|
||||
showing_month_as_digits: is_month_numeric
|
||||
end
|
||||
|
||||
set_month_text
|
||||
-- Make the month appear as text.
|
||||
-- It may be full text or abbriviated depending on `is_format_short'.
|
||||
do
|
||||
is_month_numeric := False
|
||||
ensure
|
||||
showing_month_as_text: not is_month_numeric
|
||||
end
|
||||
|
||||
set_pad_zeros
|
||||
-- Make sure the `day_string', `year_string', and `month_string' (when
|
||||
-- `is_month_numeric') are padded with leading zeros when necessary.
|
||||
-- For example, in numeric form "9 Jan 2004" may be shown as "09/01/04".
|
||||
do
|
||||
is_zero_padded := True
|
||||
ensure
|
||||
zero_padding_set: is_zero_padded
|
||||
end
|
||||
|
||||
set_hide_zeros
|
||||
-- Do not pad numeric values with leading zeros.
|
||||
do
|
||||
is_zero_padded := False
|
||||
ensure
|
||||
not_padded: not is_zero_padded
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
save_format
|
||||
-- Save the `format' for restoration later.
|
||||
do
|
||||
saved := format
|
||||
ensure
|
||||
format_saved: saved = format
|
||||
end
|
||||
|
||||
restore_format
|
||||
-- Reset `format' to the value `saved' by a call to `save_format'.
|
||||
do
|
||||
format := saved
|
||||
ensure
|
||||
format_restored: format = saved
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
is_valid (a_string: STRING): BOOLEAN
|
||||
-- Is `a_string' convertable to a date?
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
do
|
||||
Result := parsed (a_string) /= Void
|
||||
ensure
|
||||
definition: Result implies parsed (a_string) /= Void
|
||||
end
|
||||
|
||||
is_weekday_included: BOOLEAN
|
||||
-- Is the day of week (ie "Monday") in ymd_time string.
|
||||
|
||||
is_short_format: BOOLEAN
|
||||
-- Is the year two digits instead of four and
|
||||
-- is the month abriviated?
|
||||
|
||||
is_month_numeric: BOOLEAN
|
||||
-- Is the `month_string' shown as digits? (As opposed to a
|
||||
-- textual representation such as "January".)
|
||||
|
||||
is_zero_padded: BOOLEAN
|
||||
-- Are digital values to be padded with leading zero's if
|
||||
-- shorter than normal?
|
||||
|
||||
is_index_in_day_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
-- index_large_enough: a_index >= 1
|
||||
local
|
||||
s, ds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ds := day_string (a_ymd_time)
|
||||
i := s.substring_index (ds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_month_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
require
|
||||
ymd_time_exists: a_ymd_time /= Void
|
||||
local
|
||||
s, ms: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ms := month_string (a_ymd_time)
|
||||
i := s.substring_index (ms, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ms.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_year_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, ys: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
ys := year_string (a_ymd_time)
|
||||
i := s.substring_index (ys, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + ys.count-1
|
||||
end
|
||||
end
|
||||
|
||||
is_index_in_weekday_string (a_ymd_time: like time_anchor; a_index: INTEGER): BOOLEAN
|
||||
local
|
||||
s, wds: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
s := to_string (a_ymd_time)
|
||||
wds := weekday_string (a_ymd_time)
|
||||
i := s.substring_index (wds, 1)
|
||||
if i > 0 then
|
||||
Result := a_index >= i and a_index <= i + wds.count-1
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
parsed (a_string: STRING): like time_anchor
|
||||
-- Attemp to convert `a_string' to a {YMD_TIME}, returning
|
||||
-- Void if unable.
|
||||
require
|
||||
string_exists: a_string /= Void
|
||||
string_has_length: a_string.count >= 1
|
||||
local
|
||||
p: YMD_TIME_PARSER
|
||||
do
|
||||
create p
|
||||
-- p.set_format (format)
|
||||
-- p.parse_string (a_string)
|
||||
-- Result := p.last_value
|
||||
check
|
||||
fix_me: False then
|
||||
end
|
||||
end
|
||||
|
||||
format: INTEGER
|
||||
|
||||
saved: INTEGER
|
||||
-- used to save the format.
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMD_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
valid_ymd_time_format: is_valid_format (format)
|
||||
|
||||
end
|
||||
|
||||
|
68
jj_temporal/jj_t/formatters/ymdhms_duration_formatter.e
Normal file
68
jj_temporal/jj_t/formatters/ymdhms_duration_formatter.e
Normal file
@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMDHMS_DURATION}'s to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymdhms_duration' is more
|
||||
relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_DURATION_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_DURATION_FORMATTER
|
||||
rename
|
||||
to_string as time_string,
|
||||
set_separator as set_time_separator,
|
||||
separator as time_separator,
|
||||
string_to_duration as hms_string_to_duration,
|
||||
format as hms_format
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_DURATION_FORMATTER
|
||||
rename
|
||||
to_string as date_string,
|
||||
set_separator as set_date_separator,
|
||||
separator as date_separator,
|
||||
string_to_duration as ymd_string_to_duration,
|
||||
format as ymd_format
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
default_create
|
||||
--
|
||||
do
|
||||
Precursor {HMS_DURATION_FORMATTER}
|
||||
Precursor {YMD_DURATION_FORMATTER}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
to_string (a_duration: YMDHMS_DURATION): STRING
|
||||
-- the whole duration as a string
|
||||
require
|
||||
duration_exists: a_duration /= Void
|
||||
do
|
||||
create Result.make (30)
|
||||
Result.append (date_string (a_duration))
|
||||
Result.append (" ")
|
||||
Result.append (time_string (a_duration))
|
||||
end
|
||||
|
||||
end -- class YMDHMS_DURATION_FORMATTER
|
126
jj_temporal/jj_t/formatters/ymdhms_time_formatter.e
Normal file
126
jj_temporal/jj_t/formatters/ymdhms_time_formatter.e
Normal file
@ -0,0 +1,126 @@
|
||||
note
|
||||
description: "[
|
||||
Utility class for converting {YMDHMS_TIME}'s (i.e. date/times) to and from
|
||||
strings based on a selected `format'. While the string given
|
||||
by feature `as_string' is set based on the format, the parsing
|
||||
of a string to a date in feature `to_ymd_time' is more relaxed.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMDHMS_TIME_FORMATTER
|
||||
|
||||
inherit
|
||||
|
||||
HMS_TIME_FORMATTER
|
||||
rename
|
||||
set_separator as set_time_separator,
|
||||
separator as time_separator
|
||||
redefine
|
||||
default_create,
|
||||
to_string,
|
||||
time_anchor
|
||||
end
|
||||
|
||||
YMD_TIME_FORMATTER
|
||||
rename
|
||||
set_separator as set_date_separator,
|
||||
separator as date_separator
|
||||
redefine
|
||||
default_create,
|
||||
to_string,
|
||||
time_anchor
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
Precursor {HMS_TIME_FORMATTER}
|
||||
Precursor {YMD_TIME_FORMATTER}
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
to_string (a_time: like time_anchor): STRING
|
||||
-- the whole date as a string
|
||||
do
|
||||
create Result.make (30)
|
||||
if not is_date_hidden then
|
||||
Result.append (Precursor {YMD_TIME_FORMATTER} (a_time))
|
||||
Result.append (" ")
|
||||
end
|
||||
if not is_time_hidden then
|
||||
Result.append (Precursor {HMS_TIME_FORMATTER} (a_time))
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_time_hidden: BOOLEAN
|
||||
-- Will `to_string' not include the time?
|
||||
|
||||
is_date_hidden: BOOLEAN
|
||||
-- Will `to_string' not include the date?
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
hide_time
|
||||
-- Make `to_string' produce a string showing the date only;
|
||||
-- the time portion will not show.
|
||||
do
|
||||
is_time_hidden := True
|
||||
is_date_hidden := False
|
||||
ensure
|
||||
time_is_hidden: is_time_hidden
|
||||
date_is_shown: not is_date_hidden
|
||||
end
|
||||
|
||||
hide_date
|
||||
-- Make `a_string' produce a string showing the time only;
|
||||
-- the date portionn will not show.
|
||||
do
|
||||
is_date_hidden := True
|
||||
is_time_hidden := False
|
||||
ensure
|
||||
date_is_hidden: is_date_hidden
|
||||
time_is_shown: not is_time_hidden
|
||||
end
|
||||
|
||||
show_date_and_time
|
||||
-- Make `to_string' produce a string showing both the date
|
||||
-- portion and the time portion. This is the default.
|
||||
do
|
||||
is_date_hidden := False
|
||||
is_time_hidden := False
|
||||
ensure
|
||||
date_is_shown: not is_date_hidden
|
||||
time_is_shown: not is_time_hidden
|
||||
end
|
||||
|
||||
feature {NONE} -- Anchors (for covariant redefinitions)
|
||||
|
||||
time_anchor: YMDHMS_TIME
|
||||
-- Not to be called; just used to anchor types.
|
||||
require else
|
||||
not_callable: False
|
||||
do
|
||||
check
|
||||
do_not_call: False then
|
||||
-- Because gives no info; simply used as anchor.
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
not_both_date_and_time_hidden: not (is_date_hidden and is_time_hidden)
|
||||
|
||||
end
|
25
jj_temporal/jj_t/jj_temporal.ecf
Normal file
25
jj_temporal/jj_t/jj_temporal.ecf
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-21-0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-21-0 http://www.eiffel.com/developers/xml/configuration-1-21-0.xsd"
|
||||
name="jj_temporal"
|
||||
uuid="1C5069C0-C04D-4077-8193-FB226A11EEE7"
|
||||
library_target="jj_temporal">
|
||||
<target name="jj_temporal">
|
||||
<root all_classes="true"/>
|
||||
<option warning="warning" full_class_checking="true" is_attached_by_default="true" void_safety="all">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<cluster name="jj_temporal" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/demo$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/docs$</exclude>
|
||||
</file_rule>
|
||||
<file_rule>
|
||||
<exclude>^/parsers/gobo_files$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
10
jj_temporal/jj_t/parsers/classes/ymd_time_parser.e
Normal file
10
jj_temporal/jj_t/parsers/classes/ymd_time_parser.e
Normal file
@ -0,0 +1,10 @@
|
||||
note
|
||||
description: "Summary description for {YMD_TIME_PARSER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
YMD_TIME_PARSER
|
||||
|
||||
end
|
130
jj_temporal/jj_t/parsers/classes/ymd_time_parser_routines.e
Normal file
130
jj_temporal/jj_t/parsers/classes/ymd_time_parser_routines.e
Normal file
@ -0,0 +1,130 @@
|
||||
note
|
||||
description: "[
|
||||
Routines used by the {YMD_TIME_PARSER}. These were put here to
|
||||
ease the editting. The text of class {YMD_TIME_PARSER} is produced
|
||||
by "geyacc" from a discription file, so every time a change is
|
||||
made "geyacc" must be run (from a dos prompt), the files moved, etc.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_PARSER_ROUTINES
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
|
||||
feature -- Access
|
||||
|
||||
format: INTEGER
|
||||
-- How the date should appear (i.e. "dd mmm yyyy", "mm/dd/yy", etc
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_format (a_format: INTEGER)
|
||||
-- Change `format'
|
||||
require
|
||||
valid_format: is_valid_format (a_format)
|
||||
do
|
||||
format := a_format
|
||||
ensure
|
||||
format_was_set: format = a_format
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
process_ambiguous_day (a_possible_day, a_month, a_year: INTEGER): detachable YMD_TIME
|
||||
-- Return a date if `a_possible_day' is valid for the know values of
|
||||
-- `a_month' and `a_year'; void otherwise.
|
||||
require
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
valid_year: a_year /= 0
|
||||
local
|
||||
d: YMD_TIME
|
||||
do
|
||||
create d.set (a_year, a_month, 1)
|
||||
if a_possible_day >= 1 and a_possible_day <= d.last_day_of_month then
|
||||
create Result.set (a_year, a_month, a_possible_day)
|
||||
end
|
||||
end
|
||||
|
||||
process_ambiguous_day_month (a_possible_day, a_possible_month, a_year: INTEGER): YMD_TIME
|
||||
-- Only the year is known; determine which of the other two values is
|
||||
-- the month and which is the day.
|
||||
require
|
||||
valid_year: a_year /= 0
|
||||
unknown_day_from_scanner: a_possible_day <= 12
|
||||
unknown_month_from_scanner: a_possible_month <= 12
|
||||
do
|
||||
create Result.set (a_year, a_possible_month, a_possible_day)
|
||||
end
|
||||
|
||||
process_ambiguous_day_year (a_possible_day, a_month, a_possible_year: INTEGER): YMD_TIME
|
||||
-- Only the month is know for sure.
|
||||
require
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
unknown_day_from_scanner: a_possible_day <= 12
|
||||
unknown_year_from_scanner: a_possible_year <= 12
|
||||
do
|
||||
create Result.set (a_possible_day, a_month, a_possible_year)
|
||||
end
|
||||
|
||||
process_unspecified (a_day, a_month, a_year: INTEGER): YMD_TIME
|
||||
-- One of `a_day' or `a_year' was not specified in the scanned string.
|
||||
-- The unspecified one will be 0.
|
||||
require
|
||||
one_zero: a_day = 0 or a_year = 0
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
local
|
||||
d: YMD_TIME
|
||||
do
|
||||
if a_day = 0 then
|
||||
create Result.set (a_year, a_month, 1)
|
||||
else
|
||||
create d.set_now
|
||||
create Result.set_now
|
||||
Result.set_day (a_day)
|
||||
Result.set_month (a_month)
|
||||
if Result < d then
|
||||
Result.set_year (Result.year + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
process_three_numbers (int_1, int_2, int_3: INTEGER): YMD_TIME
|
||||
-- Scanner encountered a three-integer date and was unable to determine
|
||||
-- from the context what any of them mean.
|
||||
require
|
||||
int_1_is_number: int_1 >= 1 and int_1 <= 31
|
||||
int_2_is_number: int_2 >= 1 and int_2 <= 31
|
||||
int_3_is_number: int_3 >= 1 and int_3 <= 31
|
||||
do
|
||||
|
||||
create Result.set (int_1, int_2, int_3)
|
||||
end
|
||||
|
||||
process_two_numbers (int_1, int_2: INTEGER): YMD_TIME
|
||||
-- Scanner only found 2 numbers and unknow what they represent.
|
||||
require
|
||||
int_1_is_number: int_1 >= 1 and int_1 <= 31
|
||||
int_2_is_number: int_2 >= 1 and int_2 <= 31
|
||||
do
|
||||
create Result.set_now
|
||||
Result.set_day (int_1)
|
||||
Result.set_month (int_2)
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
valid_ymd_time_format: is_valid_format (format)
|
||||
|
||||
end -- Class YMD_TIME_PARSER_ROUTINES
|
69
jj_temporal/jj_t/parsers/classes/ymd_time_scanner_routines.e
Normal file
69
jj_temporal/jj_t/parsers/classes/ymd_time_scanner_routines.e
Normal file
@ -0,0 +1,69 @@
|
||||
note
|
||||
description: "[
|
||||
Routines used by the {YMD_TIME_SCANNER}. These were put here to
|
||||
ease the editting. The text of class {YMD_TIME_SCANNER} is produced
|
||||
by "gelex" from a discription file, so every time a change is
|
||||
made "geyacc" must be run (from a dos prompt), the files moved, etc.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature {NONE} -- Inititalization
|
||||
|
||||
default_create
|
||||
|
||||
-- Create an instance
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: detachable STRING
|
||||
-- Last string value read to pass to parser
|
||||
|
||||
last_integer: INTEGER
|
||||
-- Last integer value read to pass to parser.
|
||||
|
||||
last_value: detachable ANY
|
||||
-- Last value read by the scanner
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
comas_removed (a_number_string: STRING): STRING
|
||||
-- Return the string without comas.
|
||||
-- Used to remove comas from reals or strings.
|
||||
local
|
||||
s: STRING
|
||||
i, n: INTEGER
|
||||
c: CHARACTER
|
||||
do
|
||||
create Result.make (200)
|
||||
s := a_number_string
|
||||
n := a_number_string.count
|
||||
from i := 1 until i > n
|
||||
loop
|
||||
c := s.item (i)
|
||||
if c /= ',' then
|
||||
Result.append_character (c)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
end -- class YMD_TIME_SCANNER_ROUTINES
|
49
jj_temporal/jj_t/parsers/classes/ymd_time_tokens.e
Normal file
49
jj_temporal/jj_t/parsers/classes/ymd_time_tokens.e
Normal file
@ -0,0 +1,49 @@
|
||||
note
|
||||
|
||||
description: "Parser token codes"
|
||||
generator: "geyacc version 3.4"
|
||||
|
||||
class YMD_TIME_TOKENS
|
||||
|
||||
|
||||
feature -- Last values
|
||||
|
||||
last_any_value: detachable ANY
|
||||
|
||||
feature -- Access
|
||||
|
||||
token_name (a_token: INTEGER): STRING
|
||||
-- Name of token `a_token'
|
||||
do
|
||||
inspect a_token
|
||||
when 0 then
|
||||
Result := "EOF token"
|
||||
when -1 then
|
||||
Result := "Error token"
|
||||
when SCAN_ERROR_TOKEN then
|
||||
Result := "SCAN_ERROR_TOKEN"
|
||||
when WEEKDAY_TOKEN then
|
||||
Result := "WEEKDAY_TOKEN"
|
||||
when YEAR_TOKEN then
|
||||
Result := "YEAR_TOKEN"
|
||||
when MONTH_TOKEN then
|
||||
Result := "MONTH_TOKEN"
|
||||
when YEAR_OR_DAY_TOKEN then
|
||||
Result := "YEAR_OR_DAY_TOKEN"
|
||||
when NUMBER_TOKEN then
|
||||
Result := "NUMBER_TOKEN"
|
||||
else
|
||||
Result := "Unknown token"
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Token codes
|
||||
|
||||
SCAN_ERROR_TOKEN: INTEGER = 258
|
||||
WEEKDAY_TOKEN: INTEGER = 259
|
||||
YEAR_TOKEN: INTEGER = 260
|
||||
MONTH_TOKEN: INTEGER = 261
|
||||
YEAR_OR_DAY_TOKEN: INTEGER = 262
|
||||
NUMBER_TOKEN: INTEGER = 263
|
||||
|
||||
end
|
BIN
jj_temporal/jj_t/parsers/gobo_files/gelex.exe
Normal file
BIN
jj_temporal/jj_t/parsers/gobo_files/gelex.exe
Normal file
Binary file not shown.
BIN
jj_temporal/jj_t/parsers/gobo_files/geyacc.exe
Normal file
BIN
jj_temporal/jj_t/parsers/gobo_files/geyacc.exe
Normal file
Binary file not shown.
BIN
jj_temporal/jj_t/parsers/gobo_files/old_gelex.exe
Normal file
BIN
jj_temporal/jj_t/parsers/gobo_files/old_gelex.exe
Normal file
Binary file not shown.
BIN
jj_temporal/jj_t/parsers/gobo_files/old_geyacc.exe
Normal file
BIN
jj_temporal/jj_t/parsers/gobo_files/old_geyacc.exe
Normal file
Binary file not shown.
7
jj_temporal/jj_t/parsers/gobo_files/y.bat
Normal file
7
jj_temporal/jj_t/parsers/gobo_files/y.bat
Normal file
@ -0,0 +1,7 @@
|
||||
cd d:
|
||||
cd e_source
|
||||
cd parser_tests
|
||||
cd date_parser
|
||||
cd discription_files
|
||||
geyacc -t ymd_time_tokens -o ymd_time_parser.e ymd_time_parser.y
|
||||
gelex -o ymd_time_scanner.e ymd_time_scanner.l
|
191
jj_temporal/jj_t/parsers/gobo_files/ymd_time_parser.y
Normal file
191
jj_temporal/jj_t/parsers/gobo_files/ymd_time_parser.y
Normal file
@ -0,0 +1,191 @@
|
||||
%{
|
||||
indexing
|
||||
description: "[
|
||||
Parser for reading in a string and converting it to a date.
|
||||
This file was produced by 'geyacc' (from the gobo tools cluster)
|
||||
using file 'ymd_time_parser.y'.
|
||||
]"
|
||||
date: "17 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_PARSER
|
||||
|
||||
inherit
|
||||
|
||||
YY_PARSER_SKELETON
|
||||
rename
|
||||
make as make_parser_skeleton
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_PARSER_ROUTINES
|
||||
rename
|
||||
last_value as last_scanner_value
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER
|
||||
rename
|
||||
last_value as last_scanner_value
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create is
|
||||
-- Create a new Eiffel parser.
|
||||
do
|
||||
Precursor {YMD_TIME_SCANNER}
|
||||
make_parser_skeleton
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_value: YMD_TIME
|
||||
-- The result of parsing
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
parse_string (a_string: STRING) is
|
||||
-- Parse `a_string'.
|
||||
local
|
||||
b: KL_CHARACTER_BUFFER
|
||||
yy_buf: YY_BUFFER
|
||||
f: FILE
|
||||
s: STRING
|
||||
do
|
||||
reset
|
||||
-- The `b' must end in "%U%U". I don't know why.
|
||||
-- so append it onto the end of a copy of `a_string'.
|
||||
s := deep_clone (a_string)
|
||||
s.append ("%U%U")
|
||||
create b.make_from_string (s)
|
||||
create yy_buf.make_from_buffer (b)
|
||||
set_input_buffer (yy_buf)
|
||||
parse
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------
|
||||
-------------------- Following created by GeYacc ----------------------------------
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%token SCAN_ERROR_TOKEN
|
||||
|
||||
%token WEEKDAY_TOKEN
|
||||
%token YEAR_TOKEN
|
||||
%token MONTH_TOKEN
|
||||
%token YEAR_OR_DAY_TOKEN
|
||||
%token NUMBER_TOKEN
|
||||
|
||||
%type <YMD_TIME> Date
|
||||
%type <YMD_TIME> Ambiguous_day
|
||||
%type <YMD_TIME> Ambiguous_day_month
|
||||
%type <YMD_TIME> Unspecified
|
||||
%type <YMD_TIME> Weekday_included
|
||||
%type <YMD_TIME> Three_numbers
|
||||
%type <YMD_TIME> Two_numbers
|
||||
|
||||
%type <INTEGER> Month
|
||||
%type <INTEGER> Year
|
||||
%type <INTEGER> Year_or_day
|
||||
%type <INTEGER> Number
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
%%
|
||||
|
||||
Date: -- Empty { parsed_result := "No date entered" }
|
||||
| Ambiguous_day { $$ := $1 last_value := $$ }
|
||||
| Ambiguous_day_month { $$ := $1 last_value := $$ }
|
||||
| Unspecified { $$ := $1 last_value := $$ }
|
||||
| Three_numbers { $$ := $1 last_value := $$ }
|
||||
| Two_numbers { $$ := $1 last_value := $$ }
|
||||
| Weekday_included { $$ := $1 last_value := $$ }
|
||||
-- | SCAN_ERROR_TOKEN { $$ := last_scanner_value last_value := $$ }
|
||||
;
|
||||
|
||||
-- The Month and Year are known.
|
||||
Ambiguous_day: Number Month Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Year_or_day Month Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Month Year_or_day Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
| Month Number Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
;
|
||||
|
||||
-- Only the Year is certain.
|
||||
Ambiguous_day_month: Year_or_day Number Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Number Year_or_day Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
| Year Year_or_day Number { $$ := process_ambiguous_day ($2, $3, $1) }
|
||||
| Year Number Year_or_day { $$ := process_ambiguous_day ($3, $2, $1) }
|
||||
| Number Number Year { $$ := process_ambiguous_day_month ($1, $2, $3) }
|
||||
| Year Number Number { $$ := process_ambiguous_day_month ($2, $3, $1) }
|
||||
;
|
||||
|
||||
-- Two values input and at least one can be identified; assumptions are made about the unknowns.
|
||||
Unspecified: Month Year { $$ := process_unspecified (0, $1, $2) }
|
||||
| Year Month { $$ := process_unspecified (0, $2, $1) }
|
||||
| Year_or_day Month { $$ := process_unspecified ($1, $2, 0) }
|
||||
| Month Year_or_day { $$ := process_unspecified ($2, $1, 0) }
|
||||
| Number Year { $$ := process_unspecified (0, $1, $2) }
|
||||
| Year Number { $$ := process_unspecified (0, $2, $1) }
|
||||
| Number Month { $$ := process_unspecified ($1, $2, 0) }
|
||||
| Month Number { $$ := process_unspecified ($2, $1, 0) }
|
||||
;
|
||||
|
||||
-- A date with the weekday included; the weekday is ignored.
|
||||
Weekday_included: Weekday Ambiguous_day { $$ := $2 }
|
||||
| Weekday Ambiguous_day_month { $$ := $2 }
|
||||
| Weekday Unspecified { $$ := $2 }
|
||||
| Weekday Three_numbers { $$ := $2 }
|
||||
| Weekday Two_numbers { $$ := $2 }
|
||||
;
|
||||
|
||||
-- The date is entered as three numbers and scanner is unable to deduce from
|
||||
-- the values which one is day, year, and so on.
|
||||
Three_numbers: Number Number Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Year_or_day Number Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Number Year_or_day Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Number Number Year_or_day { $$ := process_three_numbers ($1, $2, $3) }
|
||||
;
|
||||
|
||||
-- The date was enterred as only two numbers and the scanner was unable
|
||||
-- to deduce thier meanings.
|
||||
Two_numbers: Number Number { $$ := process_two_numbers ($1, $2) }
|
||||
| Year_or_day Number { $$ := process_two_numbers ($1, $2) }
|
||||
| Number Year_or_day { $$ := process_two_numbers ($1, $2) }
|
||||
;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Weekday: WEEKDAY_TOKEN { -- do nothing as result is not needed
|
||||
}
|
||||
;
|
||||
|
||||
Month: MONTH_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Year: YEAR_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Year_or_day: YEAR_OR_DAY_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Number: NUMBER_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
|
||||
end -- class YMD_TIME_PARSER
|
149
jj_temporal/jj_t/parsers/gobo_files/ymd_time_scanner.l
Normal file
149
jj_temporal/jj_t/parsers/gobo_files/ymd_time_scanner.l
Normal file
@ -0,0 +1,149 @@
|
||||
%{
|
||||
indexing
|
||||
description: "[
|
||||
Scanner for reading in a string and converting it to a date.
|
||||
This file was produced by 'gelex' (from the gobo tools cluster)
|
||||
using file "ymd_time_scanner.l".
|
||||
]"
|
||||
date: "17 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_SCANNER
|
||||
|
||||
inherit
|
||||
|
||||
YY_COMPRESSED_SCANNER_SKELETON
|
||||
export
|
||||
{NONE} all
|
||||
{ANY} scanning_error
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
UT_CHARACTER_CODES
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_TOKENS
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create is
|
||||
-- Create a scanner object
|
||||
do
|
||||
make
|
||||
Precursor {YMD_TIME_SCANNER_ROUTINES}
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
scan_string (a_string: STRING) is
|
||||
-- Scan `a_string'
|
||||
local
|
||||
b: KL_CHARACTER_BUFFER
|
||||
yy_buf: YY_BUFFER
|
||||
f: FILE
|
||||
s: STRING
|
||||
do
|
||||
-- The `b' must end in "%U%U". I don't know why.
|
||||
-- so append it onto the end of a copy of `a_string'.
|
||||
s := deep_clone (a_string)
|
||||
s.append ("%U%U")
|
||||
create b.make_from_string (s)
|
||||
create yy_buf.make_from_buffer (b)
|
||||
set_input_buffer (yy_buf)
|
||||
scan
|
||||
end
|
||||
|
||||
print_values is
|
||||
do
|
||||
io.put_string ("token = ")
|
||||
io.put_string (token_name (last_token))
|
||||
io.put_string (" value = ")
|
||||
if last_value /= Void then
|
||||
io.put_string (last_value.out)
|
||||
else
|
||||
io.put_string ("Void")
|
||||
end
|
||||
io.new_line
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
----------------------- Following code produce by Gelex ----------------------
|
||||
|
||||
%}
|
||||
|
||||
--%x IN_STR -- line 50
|
||||
%option outfile="ymd_time_scanner.e"
|
||||
|
||||
|
||||
IDENTIFIER [a-zA-Z][a-zA-Z]*
|
||||
|
||||
DIGIT [0-9]
|
||||
INTEGER {DIGIT}+|{DIGIT}{1,3}(,{DIGIT}{3})+
|
||||
|
||||
SEPARATORS [:./\\,\- \t\n\r]+
|
||||
|
||||
%%
|
||||
|
||||
{INTEGER} {
|
||||
last_integer := comas_removed (text).to_integer
|
||||
last_value := last_integer
|
||||
if last_integer > 31 then
|
||||
last_token := YEAR_TOKEN
|
||||
elseif last_integer > 12 then
|
||||
last_token := YEAR_OR_DAY_TOKEN
|
||||
else
|
||||
last_token := NUMBER_TOKEN
|
||||
end
|
||||
print_values
|
||||
}
|
||||
|
||||
{IDENTIFIER} { if is_month (text) then
|
||||
last_token := MONTH_TOKEN
|
||||
last_integer := get_month (text)
|
||||
last_value := last_integer
|
||||
elseif is_weekday (text) then
|
||||
last_token := WEEKDAY_TOKEN
|
||||
last_string := text
|
||||
last_value := text
|
||||
else
|
||||
last_token := SCAN_ERROR_TOKEN
|
||||
last_value := last_string
|
||||
print_values
|
||||
end
|
||||
print_values
|
||||
}
|
||||
|
||||
{SEPARATORS} { last_value := text
|
||||
print_values
|
||||
}
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
end -- class YMD_TIME_SCANNER
|
25
jj_temporal/jj_temporal.ecf
Normal file
25
jj_temporal/jj_temporal.ecf
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-21-0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-21-0 http://www.eiffel.com/developers/xml/configuration-1-21-0.xsd"
|
||||
name="jj_temporal"
|
||||
uuid="1C5069C0-C04D-4077-8193-FB226A11EEE7"
|
||||
library_target="jj_temporal">
|
||||
<target name="jj_temporal">
|
||||
<root all_classes="true"/>
|
||||
<option warning="warning" full_class_checking="true" is_attached_by_default="true" void_safety="all">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<cluster name="jj_temporal" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/demo$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/docs$</exclude>
|
||||
</file_rule>
|
||||
<file_rule>
|
||||
<exclude>^/parsers/gobo_files$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
10
jj_temporal/parsers/classes/ymd_time_parser.e
Normal file
10
jj_temporal/parsers/classes/ymd_time_parser.e
Normal file
@ -0,0 +1,10 @@
|
||||
note
|
||||
description: "Summary description for {YMD_TIME_PARSER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
YMD_TIME_PARSER
|
||||
|
||||
end
|
130
jj_temporal/parsers/classes/ymd_time_parser_routines.e
Normal file
130
jj_temporal/parsers/classes/ymd_time_parser_routines.e
Normal file
@ -0,0 +1,130 @@
|
||||
note
|
||||
description: "[
|
||||
Routines used by the {YMD_TIME_PARSER}. These were put here to
|
||||
ease the editting. The text of class {YMD_TIME_PARSER} is produced
|
||||
by "geyacc" from a discription file, so every time a change is
|
||||
made "geyacc" must be run (from a dos prompt), the files moved, etc.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_PARSER_ROUTINES
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
|
||||
feature -- Access
|
||||
|
||||
format: INTEGER
|
||||
-- How the date should appear (i.e. "dd mmm yyyy", "mm/dd/yy", etc
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_format (a_format: INTEGER)
|
||||
-- Change `format'
|
||||
require
|
||||
valid_format: is_valid_format (a_format)
|
||||
do
|
||||
format := a_format
|
||||
ensure
|
||||
format_was_set: format = a_format
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
process_ambiguous_day (a_possible_day, a_month, a_year: INTEGER): detachable YMD_TIME
|
||||
-- Return a date if `a_possible_day' is valid for the know values of
|
||||
-- `a_month' and `a_year'; void otherwise.
|
||||
require
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
valid_year: a_year /= 0
|
||||
local
|
||||
d: YMD_TIME
|
||||
do
|
||||
create d.set (a_year, a_month, 1)
|
||||
if a_possible_day >= 1 and a_possible_day <= d.last_day_of_month then
|
||||
create Result.set (a_year, a_month, a_possible_day)
|
||||
end
|
||||
end
|
||||
|
||||
process_ambiguous_day_month (a_possible_day, a_possible_month, a_year: INTEGER): YMD_TIME
|
||||
-- Only the year is known; determine which of the other two values is
|
||||
-- the month and which is the day.
|
||||
require
|
||||
valid_year: a_year /= 0
|
||||
unknown_day_from_scanner: a_possible_day <= 12
|
||||
unknown_month_from_scanner: a_possible_month <= 12
|
||||
do
|
||||
create Result.set (a_year, a_possible_month, a_possible_day)
|
||||
end
|
||||
|
||||
process_ambiguous_day_year (a_possible_day, a_month, a_possible_year: INTEGER): YMD_TIME
|
||||
-- Only the month is know for sure.
|
||||
require
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
unknown_day_from_scanner: a_possible_day <= 12
|
||||
unknown_year_from_scanner: a_possible_year <= 12
|
||||
do
|
||||
create Result.set (a_possible_day, a_month, a_possible_year)
|
||||
end
|
||||
|
||||
process_unspecified (a_day, a_month, a_year: INTEGER): YMD_TIME
|
||||
-- One of `a_day' or `a_year' was not specified in the scanned string.
|
||||
-- The unspecified one will be 0.
|
||||
require
|
||||
one_zero: a_day = 0 or a_year = 0
|
||||
valid_month: a_month >= 1 and a_month <= 12
|
||||
local
|
||||
d: YMD_TIME
|
||||
do
|
||||
if a_day = 0 then
|
||||
create Result.set (a_year, a_month, 1)
|
||||
else
|
||||
create d.set_now
|
||||
create Result.set_now
|
||||
Result.set_day (a_day)
|
||||
Result.set_month (a_month)
|
||||
if Result < d then
|
||||
Result.set_year (Result.year + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
process_three_numbers (int_1, int_2, int_3: INTEGER): YMD_TIME
|
||||
-- Scanner encountered a three-integer date and was unable to determine
|
||||
-- from the context what any of them mean.
|
||||
require
|
||||
int_1_is_number: int_1 >= 1 and int_1 <= 31
|
||||
int_2_is_number: int_2 >= 1 and int_2 <= 31
|
||||
int_3_is_number: int_3 >= 1 and int_3 <= 31
|
||||
do
|
||||
|
||||
create Result.set (int_1, int_2, int_3)
|
||||
end
|
||||
|
||||
process_two_numbers (int_1, int_2: INTEGER): YMD_TIME
|
||||
-- Scanner only found 2 numbers and unknow what they represent.
|
||||
require
|
||||
int_1_is_number: int_1 >= 1 and int_1 <= 31
|
||||
int_2_is_number: int_2 >= 1 and int_2 <= 31
|
||||
do
|
||||
create Result.set_now
|
||||
Result.set_day (int_1)
|
||||
Result.set_month (int_2)
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
valid_ymd_time_format: is_valid_format (format)
|
||||
|
||||
end -- Class YMD_TIME_PARSER_ROUTINES
|
69
jj_temporal/parsers/classes/ymd_time_scanner_routines.e
Normal file
69
jj_temporal/parsers/classes/ymd_time_scanner_routines.e
Normal file
@ -0,0 +1,69 @@
|
||||
note
|
||||
description: "[
|
||||
Routines used by the {YMD_TIME_SCANNER}. These were put here to
|
||||
ease the editting. The text of class {YMD_TIME_SCANNER} is produced
|
||||
by "gelex" from a discription file, so every time a change is
|
||||
made "geyacc" must be run (from a dos prompt), the files moved, etc.
|
||||
]"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
|
||||
inherit
|
||||
|
||||
YMD_TIME_FORMAT_CONSTANTS
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature {NONE} -- Inititalization
|
||||
|
||||
default_create
|
||||
|
||||
-- Create an instance
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_string: detachable STRING
|
||||
-- Last string value read to pass to parser
|
||||
|
||||
last_integer: INTEGER
|
||||
-- Last integer value read to pass to parser.
|
||||
|
||||
last_value: detachable ANY
|
||||
-- Last value read by the scanner
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
comas_removed (a_number_string: STRING): STRING
|
||||
-- Return the string without comas.
|
||||
-- Used to remove comas from reals or strings.
|
||||
local
|
||||
s: STRING
|
||||
i, n: INTEGER
|
||||
c: CHARACTER
|
||||
do
|
||||
create Result.make (200)
|
||||
s := a_number_string
|
||||
n := a_number_string.count
|
||||
from i := 1 until i > n
|
||||
loop
|
||||
c := s.item (i)
|
||||
if c /= ',' then
|
||||
Result.append_character (c)
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
end -- class YMD_TIME_SCANNER_ROUTINES
|
49
jj_temporal/parsers/classes/ymd_time_tokens.e
Normal file
49
jj_temporal/parsers/classes/ymd_time_tokens.e
Normal file
@ -0,0 +1,49 @@
|
||||
note
|
||||
|
||||
description: "Parser token codes"
|
||||
generator: "geyacc version 3.4"
|
||||
|
||||
class YMD_TIME_TOKENS
|
||||
|
||||
|
||||
feature -- Last values
|
||||
|
||||
last_any_value: detachable ANY
|
||||
|
||||
feature -- Access
|
||||
|
||||
token_name (a_token: INTEGER): STRING
|
||||
-- Name of token `a_token'
|
||||
do
|
||||
inspect a_token
|
||||
when 0 then
|
||||
Result := "EOF token"
|
||||
when -1 then
|
||||
Result := "Error token"
|
||||
when SCAN_ERROR_TOKEN then
|
||||
Result := "SCAN_ERROR_TOKEN"
|
||||
when WEEKDAY_TOKEN then
|
||||
Result := "WEEKDAY_TOKEN"
|
||||
when YEAR_TOKEN then
|
||||
Result := "YEAR_TOKEN"
|
||||
when MONTH_TOKEN then
|
||||
Result := "MONTH_TOKEN"
|
||||
when YEAR_OR_DAY_TOKEN then
|
||||
Result := "YEAR_OR_DAY_TOKEN"
|
||||
when NUMBER_TOKEN then
|
||||
Result := "NUMBER_TOKEN"
|
||||
else
|
||||
Result := "Unknown token"
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Token codes
|
||||
|
||||
SCAN_ERROR_TOKEN: INTEGER = 258
|
||||
WEEKDAY_TOKEN: INTEGER = 259
|
||||
YEAR_TOKEN: INTEGER = 260
|
||||
MONTH_TOKEN: INTEGER = 261
|
||||
YEAR_OR_DAY_TOKEN: INTEGER = 262
|
||||
NUMBER_TOKEN: INTEGER = 263
|
||||
|
||||
end
|
BIN
jj_temporal/parsers/gobo_files/gelex.exe
Normal file
BIN
jj_temporal/parsers/gobo_files/gelex.exe
Normal file
Binary file not shown.
BIN
jj_temporal/parsers/gobo_files/geyacc.exe
Normal file
BIN
jj_temporal/parsers/gobo_files/geyacc.exe
Normal file
Binary file not shown.
BIN
jj_temporal/parsers/gobo_files/old_gelex.exe
Normal file
BIN
jj_temporal/parsers/gobo_files/old_gelex.exe
Normal file
Binary file not shown.
BIN
jj_temporal/parsers/gobo_files/old_geyacc.exe
Normal file
BIN
jj_temporal/parsers/gobo_files/old_geyacc.exe
Normal file
Binary file not shown.
7
jj_temporal/parsers/gobo_files/y.bat
Normal file
7
jj_temporal/parsers/gobo_files/y.bat
Normal file
@ -0,0 +1,7 @@
|
||||
cd d:
|
||||
cd e_source
|
||||
cd parser_tests
|
||||
cd date_parser
|
||||
cd discription_files
|
||||
geyacc -t ymd_time_tokens -o ymd_time_parser.e ymd_time_parser.y
|
||||
gelex -o ymd_time_scanner.e ymd_time_scanner.l
|
191
jj_temporal/parsers/gobo_files/ymd_time_parser.y
Normal file
191
jj_temporal/parsers/gobo_files/ymd_time_parser.y
Normal file
@ -0,0 +1,191 @@
|
||||
%{
|
||||
indexing
|
||||
description: "[
|
||||
Parser for reading in a string and converting it to a date.
|
||||
This file was produced by 'geyacc' (from the gobo tools cluster)
|
||||
using file 'ymd_time_parser.y'.
|
||||
]"
|
||||
date: "17 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_PARSER
|
||||
|
||||
inherit
|
||||
|
||||
YY_PARSER_SKELETON
|
||||
rename
|
||||
make as make_parser_skeleton
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_PARSER_ROUTINES
|
||||
rename
|
||||
last_value as last_scanner_value
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER
|
||||
rename
|
||||
last_value as last_scanner_value
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create is
|
||||
-- Create a new Eiffel parser.
|
||||
do
|
||||
Precursor {YMD_TIME_SCANNER}
|
||||
make_parser_skeleton
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
last_value: YMD_TIME
|
||||
-- The result of parsing
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
parse_string (a_string: STRING) is
|
||||
-- Parse `a_string'.
|
||||
local
|
||||
b: KL_CHARACTER_BUFFER
|
||||
yy_buf: YY_BUFFER
|
||||
f: FILE
|
||||
s: STRING
|
||||
do
|
||||
reset
|
||||
-- The `b' must end in "%U%U". I don't know why.
|
||||
-- so append it onto the end of a copy of `a_string'.
|
||||
s := deep_clone (a_string)
|
||||
s.append ("%U%U")
|
||||
create b.make_from_string (s)
|
||||
create yy_buf.make_from_buffer (b)
|
||||
set_input_buffer (yy_buf)
|
||||
parse
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------
|
||||
-------------------- Following created by GeYacc ----------------------------------
|
||||
|
||||
|
||||
%}
|
||||
|
||||
%token SCAN_ERROR_TOKEN
|
||||
|
||||
%token WEEKDAY_TOKEN
|
||||
%token YEAR_TOKEN
|
||||
%token MONTH_TOKEN
|
||||
%token YEAR_OR_DAY_TOKEN
|
||||
%token NUMBER_TOKEN
|
||||
|
||||
%type <YMD_TIME> Date
|
||||
%type <YMD_TIME> Ambiguous_day
|
||||
%type <YMD_TIME> Ambiguous_day_month
|
||||
%type <YMD_TIME> Unspecified
|
||||
%type <YMD_TIME> Weekday_included
|
||||
%type <YMD_TIME> Three_numbers
|
||||
%type <YMD_TIME> Two_numbers
|
||||
|
||||
%type <INTEGER> Month
|
||||
%type <INTEGER> Year
|
||||
%type <INTEGER> Year_or_day
|
||||
%type <INTEGER> Number
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
%%
|
||||
|
||||
Date: -- Empty { parsed_result := "No date entered" }
|
||||
| Ambiguous_day { $$ := $1 last_value := $$ }
|
||||
| Ambiguous_day_month { $$ := $1 last_value := $$ }
|
||||
| Unspecified { $$ := $1 last_value := $$ }
|
||||
| Three_numbers { $$ := $1 last_value := $$ }
|
||||
| Two_numbers { $$ := $1 last_value := $$ }
|
||||
| Weekday_included { $$ := $1 last_value := $$ }
|
||||
-- | SCAN_ERROR_TOKEN { $$ := last_scanner_value last_value := $$ }
|
||||
;
|
||||
|
||||
-- The Month and Year are known.
|
||||
Ambiguous_day: Number Month Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Year_or_day Month Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Month Year_or_day Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
| Month Number Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
;
|
||||
|
||||
-- Only the Year is certain.
|
||||
Ambiguous_day_month: Year_or_day Number Year { $$ := process_ambiguous_day ($1, $2, $3) }
|
||||
| Number Year_or_day Year { $$ := process_ambiguous_day ($2, $1, $3) }
|
||||
| Year Year_or_day Number { $$ := process_ambiguous_day ($2, $3, $1) }
|
||||
| Year Number Year_or_day { $$ := process_ambiguous_day ($3, $2, $1) }
|
||||
| Number Number Year { $$ := process_ambiguous_day_month ($1, $2, $3) }
|
||||
| Year Number Number { $$ := process_ambiguous_day_month ($2, $3, $1) }
|
||||
;
|
||||
|
||||
-- Two values input and at least one can be identified; assumptions are made about the unknowns.
|
||||
Unspecified: Month Year { $$ := process_unspecified (0, $1, $2) }
|
||||
| Year Month { $$ := process_unspecified (0, $2, $1) }
|
||||
| Year_or_day Month { $$ := process_unspecified ($1, $2, 0) }
|
||||
| Month Year_or_day { $$ := process_unspecified ($2, $1, 0) }
|
||||
| Number Year { $$ := process_unspecified (0, $1, $2) }
|
||||
| Year Number { $$ := process_unspecified (0, $2, $1) }
|
||||
| Number Month { $$ := process_unspecified ($1, $2, 0) }
|
||||
| Month Number { $$ := process_unspecified ($2, $1, 0) }
|
||||
;
|
||||
|
||||
-- A date with the weekday included; the weekday is ignored.
|
||||
Weekday_included: Weekday Ambiguous_day { $$ := $2 }
|
||||
| Weekday Ambiguous_day_month { $$ := $2 }
|
||||
| Weekday Unspecified { $$ := $2 }
|
||||
| Weekday Three_numbers { $$ := $2 }
|
||||
| Weekday Two_numbers { $$ := $2 }
|
||||
;
|
||||
|
||||
-- The date is entered as three numbers and scanner is unable to deduce from
|
||||
-- the values which one is day, year, and so on.
|
||||
Three_numbers: Number Number Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Year_or_day Number Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Number Year_or_day Number { $$ := process_three_numbers ($1, $2, $3) }
|
||||
| Number Number Year_or_day { $$ := process_three_numbers ($1, $2, $3) }
|
||||
;
|
||||
|
||||
-- The date was enterred as only two numbers and the scanner was unable
|
||||
-- to deduce thier meanings.
|
||||
Two_numbers: Number Number { $$ := process_two_numbers ($1, $2) }
|
||||
| Year_or_day Number { $$ := process_two_numbers ($1, $2) }
|
||||
| Number Year_or_day { $$ := process_two_numbers ($1, $2) }
|
||||
;
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Weekday: WEEKDAY_TOKEN { -- do nothing as result is not needed
|
||||
}
|
||||
;
|
||||
|
||||
Month: MONTH_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Year: YEAR_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Year_or_day: YEAR_OR_DAY_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
Number: NUMBER_TOKEN { $$ := last_integer }
|
||||
;
|
||||
|
||||
|
||||
%%
|
||||
|
||||
end -- class YMD_TIME_PARSER
|
149
jj_temporal/parsers/gobo_files/ymd_time_scanner.l
Normal file
149
jj_temporal/parsers/gobo_files/ymd_time_scanner.l
Normal file
@ -0,0 +1,149 @@
|
||||
%{
|
||||
indexing
|
||||
description: "[
|
||||
Scanner for reading in a string and converting it to a date.
|
||||
This file was produced by 'gelex' (from the gobo tools cluster)
|
||||
using file "ymd_time_scanner.l".
|
||||
]"
|
||||
date: "17 Aug 04"
|
||||
author: "Jimmy J. Johnson"
|
||||
copyright: "Copyright 2009, Jimmy J. Johnson"
|
||||
license: "Eiffel Forum License v2 (see forum.txt)"
|
||||
URL: "$URL:$"
|
||||
date: "$Date: 2009-06-25 21:37:23 -0400 (Thu, 25 Jun 2009) $"
|
||||
revision: "$Revision: 7 $"
|
||||
|
||||
class YMD_TIME_SCANNER
|
||||
|
||||
inherit
|
||||
|
||||
YY_COMPRESSED_SCANNER_SKELETON
|
||||
export
|
||||
{NONE} all
|
||||
{ANY} scanning_error
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
UT_CHARACTER_CODES
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_TOKENS
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
YMD_TIME_SCANNER_ROUTINES
|
||||
export
|
||||
{NONE} all
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
create
|
||||
default_create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create is
|
||||
-- Create a scanner object
|
||||
do
|
||||
make
|
||||
Precursor {YMD_TIME_SCANNER_ROUTINES}
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
scan_string (a_string: STRING) is
|
||||
-- Scan `a_string'
|
||||
local
|
||||
b: KL_CHARACTER_BUFFER
|
||||
yy_buf: YY_BUFFER
|
||||
f: FILE
|
||||
s: STRING
|
||||
do
|
||||
-- The `b' must end in "%U%U". I don't know why.
|
||||
-- so append it onto the end of a copy of `a_string'.
|
||||
s := deep_clone (a_string)
|
||||
s.append ("%U%U")
|
||||
create b.make_from_string (s)
|
||||
create yy_buf.make_from_buffer (b)
|
||||
set_input_buffer (yy_buf)
|
||||
scan
|
||||
end
|
||||
|
||||
print_values is
|
||||
do
|
||||
io.put_string ("token = ")
|
||||
io.put_string (token_name (last_token))
|
||||
io.put_string (" value = ")
|
||||
if last_value /= Void then
|
||||
io.put_string (last_value.out)
|
||||
else
|
||||
io.put_string ("Void")
|
||||
end
|
||||
io.new_line
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
----------------------- Following code produce by Gelex ----------------------
|
||||
|
||||
%}
|
||||
|
||||
--%x IN_STR -- line 50
|
||||
%option outfile="ymd_time_scanner.e"
|
||||
|
||||
|
||||
IDENTIFIER [a-zA-Z][a-zA-Z]*
|
||||
|
||||
DIGIT [0-9]
|
||||
INTEGER {DIGIT}+|{DIGIT}{1,3}(,{DIGIT}{3})+
|
||||
|
||||
SEPARATORS [:./\\,\- \t\n\r]+
|
||||
|
||||
%%
|
||||
|
||||
{INTEGER} {
|
||||
last_integer := comas_removed (text).to_integer
|
||||
last_value := last_integer
|
||||
if last_integer > 31 then
|
||||
last_token := YEAR_TOKEN
|
||||
elseif last_integer > 12 then
|
||||
last_token := YEAR_OR_DAY_TOKEN
|
||||
else
|
||||
last_token := NUMBER_TOKEN
|
||||
end
|
||||
print_values
|
||||
}
|
||||
|
||||
{IDENTIFIER} { if is_month (text) then
|
||||
last_token := MONTH_TOKEN
|
||||
last_integer := get_month (text)
|
||||
last_value := last_integer
|
||||
elseif is_weekday (text) then
|
||||
last_token := WEEKDAY_TOKEN
|
||||
last_string := text
|
||||
last_value := text
|
||||
else
|
||||
last_token := SCAN_ERROR_TOKEN
|
||||
last_value := last_string
|
||||
print_values
|
||||
end
|
||||
print_values
|
||||
}
|
||||
|
||||
{SEPARATORS} { last_value := text
|
||||
print_values
|
||||
}
|
||||
|
||||
|
||||
%%
|
||||
|
||||
|
||||
end -- class YMD_TIME_SCANNER
|
Loading…
Reference in New Issue
Block a user