datestr.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand        --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------


immutable class DATE_SUFFICES < $ENUMS{DATE_SUFFICES}

immutable class DATE_SUFFICES < $ENUMS{DATE_SUFFICES} is -- This is an enumeration class which is provided for indicating the -- possible date suffices - as 'st', 'nd', etc. The enumeration extends over -- the values 1 to 9 since the suffix in some languages requires this. -- Version 1.0 Oct 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 5 Oct 98 kh Original include ENUM{DATE_SUFFICES} ; private const val_count : CARD := 20 ; -- The next constant routines provide the enumeration itself. First : SAME is return enum(1) end ; Second : SAME is return enum(2) end ; Third : SAME is return enum(3) end ; Other4 : SAME is return enum(4) end ; Other5 : SAME is return enum(5) end ; Other6 : SAME is return enum(6) end ; Other7 : SAME is return enum(7) end ; Other8 : SAME is return enum(8) end ; Other9 : SAME is return enum(9) end ; Other10 : SAME is return enum(10) end ; Other11 : SAME is return enum(11) end ; Other12 : SAME is return enum(12) end ; Other13 : SAME is return enum(13) end ; Other14 : SAME is return enum(14) end ; Other15 : SAME is return enum(15) end ; Other16 : SAME is return enum(16) end ; Other17 : SAME is return enum(17) end ; Other18 : SAME is return enum(18) end ; Other19 : SAME is return enum(19) end ; Other20 : SAME is return enum(20) end ; end ; -- DATE_SUFFICES

partial class DATE_STR < $TEXT, $ANCHORED_FMT

partial class DATE_STR < $TEXT, $ANCHORED_FMT is -- This partial class provides numeric date conversion routines, -- to and from character strings. -- The valid format for a date is defined for the national conventions -- the culture-dependent class CULTURE. However, dates in the following -- forms are accepted when unambiguous :-- -- -- Wed -- default to the current week -- Wednesday -- default to current week -- Wednesday 1st -- of the current month (error if 1st not Wed!!) -- 1st -- default to current month and year -- 1 -- " " " " " " -- 1st May -- default to current year to current. -- 1 May -- " " " " -- May 1 -- " " " " -- May 1st -- " " " " -- 1st May 1999 -- 1 May 1999 -- May 1 1999 -- May 1st 1999 -- (19)99 May 1st -- century is optional -- 1999 May 1 NOTE The year MUST be in full! -- 1/5/99 -- this and the next two depend -- 5/1/99 -- on the culture date spec. -- 1999-5-1 -- Version 1.1 Mar 99. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Oct 98 kh Original from DATES - heavily altered -- 29 Mar 99 kh Revised for V8 of test classes private is_noise( ch : CHAR, lib : LIBCHARS ) : BOOL pre ~void(lib) post (result = ~ch.is_alphanum(lib)) is -- This routine returns true if and only if ch is neither digit -- nor letter - ie it is syntactic noise. return ~ch.is_alphanum(lib) end ; private scan( cursor : STR_CURSOR ) : SAME pre ~void(cursor) and ~cursor.is_done post ((result.count > 0) and (initial(cursor.index) = cursor.index)) or (initial(cursor.index) < cursor.index) is -- This routine is the date scanner which attempts to determine a date -- from the string indicated. If successful then the date value is returned, -- otherwise the cursor has not been changed and, if a format error/ambiguity -- then void is returned else if a range or other value error has been -- detected then a non-void result. start_index : CARD := cursor.index ; loc_lib : LIBCHARS := cursor.buffer.index_lib ; field_cnt : CARD := 0 ; -- of fields detected in source index : CARD := 0 ; -- next array index to use! day_of_week : WEEKDAYS ; month_in_year : MONTHS ; julian_date : BOOL := false ; -- initial assumption card_year : CARD := 0 ; -- all invalid here! card_month : CARD := 0 ; card_day : CARD := 0 ; numbers : ARRAY{CARD} := ARRAY{CARD}::create(3) ; loc_str : STR ; -- miscellaneous temporary! cursor.skip_space ; if cursor.is_done then -- Oops! Nothing there! cursor.set_index(start_index) ; return from_days(0) end ; loop if cursor.is_done then -- Oops! run off the end! break! end ; if cursor.item.is_alpha(loc_lib) then -- weekday or month word! loc_start : CARD := cursor.index ; loc_str := cursor.get_pred(bind(_.is_alpha(loc_lib))) ; if field_cnt = 0 then -- try for day of week! day_of_week := WEEKDAYS::create(loc_str) ; if (day_of_week.enum = 0) then -- so try for month name month_in_year := MONTHS::create(loc_str) ; if (month_in_year.enum = 0) then -- Oops! not a known word in date cursor.set_index(start_index) ; return from_days(0) else card_month := field_cnt + 1 ; numbers[index] := month_in_year.enum ; index := index + 1 end end else if ~(month_in_year.enum = 0) then -- Oops! already got it! break! end ; month_in_year := MONTHS::create(loc_str) ; if (month_in_year.enum = 0) then -- NOT a valid 'word' - so back up cursor.set_index(loc_start) ; break! else card_month := field_cnt + 1 ; numbers[index] := month_in_year.enum ; index := index + 1 end end ; field_cnt := field_cnt + 1 elsif cursor.item.is_digit(loc_lib) then loc_str := cursor.get_pred(bind(_.is_digit(loc_lib))) ; val : CARD := CARD::create(loc_str) ; if (val >= Days_in_Year) then -- this could be a Julian date! if (card_year = 0) then card_year := field_cnt + 1 else -- already had year number! cursor.set_index(start_index) ; return from_days(0) end end ; numbers[index] := val ; index := index + 1 ; if ~cursor.is_done and cursor.item.is_alpha(loc_lib) then -- 'st', etc. if card_day /= 0 then -- Oops! already seen! cursor.set_index(start_index) ; return from_days(0) end ; loc_str := cursor.get_pred(bind(_.is_alpha(loc_lib))) ; if val > 20 then val := val % 10 end ; if DATE_SUFFICES::create(loc_str).card = val then -- OK! card_day := field_cnt + 1 else cursor.set_index(start_index) ; return from_days(0) end end ; field_cnt := field_cnt + 1 end ; if field_cnt = 3 then if cursor.is_done or (day_of_week.enum = 0) then break! else loc_str := cursor.get_pred(bind(is_noise(_,loc_lib))) end elsif field_cnt > 3 then break! elsif cursor.is_done then break! else loc_str := cursor.get_pred(bind(is_noise(_,loc_lib))) end end ; index := 0 ; -- reset for second loop! loop code : DT_CODES := loc_lib.culture.date_time.date.components.elt! ; case code when DT_CODES::Month_Day, DT_CODES::Filled_Month_Day then if julian_date then -- can't have both! cursor.set_index(start_index) ; return from_days(0) elsif card_day = 0 then index := index + 1 ; card_day := index end when DT_CODES::Year_Day then -- a Julian Date if card_day = 0 then index := index + 1 ; card_day := index ; julian_date := true end when DT_CODES::Year_Month then if julian_date then -- can't have both! cursor.set_index(start_index) ; return from_days(0) elsif card_month = 0 then index := index + 1 ; card_month := index end when DT_CODES::Century_Year, DT_CODES::Year then if card_year = 0 then index := index + 1 ; card_year := index end else -- ignore other values end end ; -- ordering done - now to check for defaults default : DATES := today ; if numbers[card_year - 1] = 0 then numbers[card_year - 1] := default.year end ; if ~julian_date then if numbers[card_month - 1] = 0 then if (month_in_year.enum = 0) then numbers[card_month - 1] := default.month_number else numbers[card_month - 1] := month_in_year.enum end end end ; if numbers[card_day - 1] = 0 then -- a real foul up! cursor.set_index(start_index) ; return from_days(0) end ; res : SAME ; if julian_date then res := create(numbers[card_day - 1], numbers[card_year - 1]) else res := create(numbers[card_day - 1], numbers[card_month - 1], numbers[card_year - 1]) end ; if ~void(day_of_week) then if day_of_week /= res.weekday then -- yet another error! cursor.set_index(start_index) ; return from_days(0) end end ; return res end ; is_date( str : STR ) : CONVERSION_RESULTS pre true post (result = CONVERSION_RESULTS::All_Right) or (result = CONVERSION_RESULTS::Out_of_Range) or (result = CONVERSION_RESULTS::Bad_Format) or (result = CONVERSION_RESULTS::Empty) is -- This routine checks that the format of of the leading characters of -- the given string in the given repertoire and encoding corresponds to that -- required for a real number, returning the relevant result state. if str.size = 0 then return CONVERSION_RESULTS::Empty end ; loc_cursor : STR_CURSOR := str.cursor ; start_index : CARD := loc_cursor.index ; val : SAME := scan(loc_cursor) ; if start_index = loc_cursor.index then -- bad or too large if void(val) then return CONVERSION_RESULTS::Bad_Format else return CONVERSION_RESULTS::Out_of_Range end else loc_cursor.set_index(start_index) ; return CONVERSION_RESULTS::All_Right end end ; build( loc_cursor : STR_CURSOR ) : SAME pre ~void(loc_cursor) and ~loc_cursor.is_done post (void(result) and (initial(loc_cursor.index) = loc_cursor.index)) or (initial(loc_cursor.index) < loc_cursor.index) is -- This routine creates the date contained in the string indicated. If -- the string does not contain a valid date then zero is returned and the -- cursor has not been moved! return scan(loc_cursor) end ; create( str : STR ) : SAME pre (is_date(str) = CONVERSION_RESULTS::All_Right) post true is -- This routine creates the whole number corresponding to the textual -- representation contained in str in the given repertoire and encoding. return build(str.cursor) end ; str( lib : LIBCHARS ) : STR is -- This routine returns the date as a string representation using the -- culture-defined formatting information. return lib.culture.date_time.date.fmt(self,lib) end ; str : STR is -- This routine returns the date as a string representation using the -- culture-dependent default formatting information. return str(LIBCHARS::default) end ; fmt( format : ANCHORED_DESCR, lib : LIBCHARS ) : STR pre ~void(format) and ~void(lib) post result.size > 0 is -- This routine returns a formatted representation of self in the given -- repertoire and encoding as dictated by the given format description. res : STR := str(lib) ; loc_fill : STR := STR::create(lib) + format.filler.char ; if res.size < format.leading then -- needs a filler res := loc_fill.repeat(format.width - res.size) + res end ; if format.trailing > 0 then return res + loc_fill.repeat(format.trailing) else return res end end ; fmt( format : ANCHORED_DESCR ) : STR pre ~void(format) post result.size > 0 is -- This routine returns a formatted representation of self in the default -- repertoire and encoding as dictated by the given format description. return fmt(format,LIBCHARS::default) end ; end ; -- DATE_STR