That's about right but I believe your indices are incorrect.
Though the documentation for parse-spec is not entirely detailed on this point, the indices to return are
selection indices, not
character indices. The difference being that selection indices are to the
left of the character indices in the string. This means that, for a fixed format of YYYYMMDD, you would return (0,4)(4,6)(6,8) instead of (0,3)(4,5)(6,7). Plus you should still set date-format-spec -- though this is not clear at all from the documentation. (Also you should set it first so that it doesn't override your parse-spec and format-spec.) Probably the documentation could be improved here, and I will make a note of that.
Also I think some of your returned indices are incorrect even with the assumption of character indices. You can tell there's an issue by pressing up and down in the DateField; this should get you single year/month/day moves, but the selection is short by an index, so looks weird, and it can miss the desired change depending on where the caret index is.
I haven't extensively tested this, but I think this reflects what you were aiming for:
Code:
{curl 7.0, 8.0 applet}
{def df =
{DateField
value = {DateTime.date},
date-format-spec = DateFieldFormatSpec.ymd
}
}
{do
set df.parse-spec =
{proc {str:String,
require-four-digit-year?:bool,
df:DateField
}:(date:DateTime,
day-start-pos:int,
day-end-pos:int,
month-start-pos:int,
month-end-pos:int,
year-start-pos:int,
year-end-pos:int
)
{if {str.find-string "/"} > -1 or {str.find-string "-"} > -1 then
{if str.size != 10 then
{return {DateTime}, 8, 10, 5, 7, 0, 4}
}
def d =
{DateTime
year = {{str.substr 0, 4}.to-int},
month = {{str.substr 5, 2}.to-int},
day = {{str.substr 8, 2}.to-int}
}
{return d, 8, 10, 5, 7, 0, 4}
else
{if str.size != 8 then
{return {DateTime}, 6, 7, 5, 6, 0, 3}
}
def d =
{DateTime
year = {{str.substr 0, 4}.to-int},
month = {{str.substr 4, 2}.to-int},
day = {{str.substr 6, 2}.to-int}
}
{return d, 6, 8, 4, 6, 0, 4}
}
}
set df.format-spec =
{proc {dt:DateTime, df:DateField}:String
{return
{format "%4d%02d%02d",
dt.info.year, dt.info.month, dt.info.day
}
}
}
}
{value df}
Note that I changed the formatting somewhat and removed the extraneous StringBufs.
As a note to others who might use this code, like the original code sample, it doesn't properly handle all possible DateField.separators, or unbalanced separators. For production, I would want to look at improving that aspect of parsing.