You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by bu...@apache.org on 2003/04/04 18:09:15 UTC
DO NOT REPLY [Bug 18713] New: -
Please add format-date() to ExsltDatetime class
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18713>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND
INSERTED IN THE BUG DATABASE.
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=18713
Please add format-date() to ExsltDatetime class
Summary: Please add format-date() to ExsltDatetime class
Product: XalanJ2
Version: 2.5Dx
Platform: All
OS/Version: All
Status: NEW
Severity: Enhancement
Priority: Other
Component: org.apache.xalan.lib
AssignedTo: xalan-dev@xml.apache.org
ReportedBy: helg.bredow@kalido.com
I've coded the implementation as well as a test case for the format-date()
function. Could you please let me know when this has been added to the next
Xalan build. Feel free to email me any questions or comments
<ma...@kalido.com>
Add the following to ExsltDatetime (you'll also need to import the
ava.util.TimeZone class). I haven't included the entire source code since it
may have changed since and it's also quite big.
<--------------
/**
* The date:format-date function formats a date/time according to a
pattern.
* <p>
* The first argument to date:format-date specifies the date/time to be
* formatted. It must be right or left-truncated date/time strings in one
of
* the formats defined in
* <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2:
Datatypes]</a>.
* The permitted formats are as follows:
* <ul>
* <li>xs:dateTime (CCYY-MM-DDThh:mm:ss)
* <li>xs:date (CCYY-MM-DD)
* <li>xs:time (hh:mm:ss)
* <li>xs:gYearMonth (CCYY-MM)
* <li>xs:gYear (CCYY)
* <li>xs:gMonthDay (--MM-DD)
* <li>xs:gMonth (--MM--)
* <li>xs:gDay (---DD)
* </ul>
* The second argument is a string that gives the format pattern used to
* format the date. The format pattern must be in the syntax specified by
* the JDK 1.1 SimpleDateFormat class. The format pattern string is
* interpreted as described for the JDK 1.1 SimpleDateFormat class.
* <p>
* If the date/time format is right-truncated (i.e. in a format other than
* xs:time, or xs:dateTime) then any missing components are assumed to be
as
* follows: if no month is specified, it is given a month of 01; if no day
* is specified, it is given a day of 01; if no time is specified, it is
* given a time of 00:00:00.
* <p>
* If the date/time format is left-truncated (i.e. xs:time, xs:gMonthDay,
* xs:gMonth or xs:gDay) and the format pattern has a token that uses a
* component that is missing from the date/time format used, then that
token
* is replaced with an empty string ('') within the result.
*
* @author Helg Bredow
*/
public static XString formatDate(String dateTime, String pattern)
{
final String yearSymbols = "Gy";
final String monthSymbols = "M";
final String daySymbols = "dDEFwW";
TimeZone timeZone;
String zone;
// Get the timezone information if it was supplied and modify the
// dateTime so that SimpleDateFormat will understand it.
if (dateTime.endsWith("Z") || dateTime.endsWith("z"))
{
timeZone = TimeZone.getTimeZone("GMT");
dateTime = dateTime.substring(0, dateTime.length()-1) + "GMT";
zone = "z";
}
else if ((dateTime.length() >= 6)
&& (dateTime.charAt(dateTime.length()-3) == ':')
&& ((dateTime.charAt(dateTime.length()-6) == '+')
|| (dateTime.charAt(dateTime.length()-6) == '-')))
{
String offset = dateTime.substring(dateTime.length()-6);
if ("+00:00".equals(offset) || "-00:00".equals(offset))
{
timeZone = TimeZone.getTimeZone("GMT");
}
else
{
timeZone = TimeZone.getTimeZone("GMT" + offset);
}
zone = "z";
// Need to adjust it since SimpleDateFormat requires GMT+hh:mm but
// we have +hh:mm.
dateTime = dateTime.substring(0, dateTime.length()-6) + "GMT" +
offset;
}
else
{
// Assume local time.
timeZone = TimeZone.getDefault();
zone = "";
// Leave off the timezone since SimpleDateFormat will assume local
// time if time zone is not included.
}
String[] formats = {dt + zone, d, gym, gy};
// Try the time format first. We need to do this to prevent
// SimpleDateFormat from interpreting a time as a year. i.e we just
need
// to check if it's a time before we check it's a year.
try
{
SimpleDateFormat inFormat = new SimpleDateFormat(t + zone);
inFormat.setLenient(false);
Date d= inFormat.parse(dateTime);
SimpleDateFormat outFormat = new SimpleDateFormat(strip
(yearSymbols + monthSymbols + daySymbols, pattern));
outFormat.setTimeZone(timeZone);
return new XString(outFormat.format(d));
}
catch (ParseException pe)
{
}
// Try the right truncated formats.
for (int i = 0; i < formats.length; i++)
{
try
{
SimpleDateFormat inFormat = new SimpleDateFormat(formats[i]);
inFormat.setLenient(false);
Date d = inFormat.parse(dateTime);
SimpleDateFormat outFormat = new SimpleDateFormat(pattern);
outFormat.setTimeZone(timeZone);
return new XString(outFormat.format(d));
}
catch (ParseException pe)
{
}
}
// Now try the left truncated ones. The Java format() function doesn't
// return the correct strings in this case. We strip any pattern
// symbols that shouldn't be output so that they are not defaulted to
// inappropriate values in the output.
try
{
SimpleDateFormat inFormat = new SimpleDateFormat(gmd);
inFormat.setLenient(false);
Date d = inFormat.parse(dateTime);
SimpleDateFormat outFormat = new SimpleDateFormat(strip
(yearSymbols, pattern));
outFormat.setTimeZone(timeZone);
return new XString(outFormat.format(d));
}
catch (ParseException pe)
{
}
try
{
SimpleDateFormat inFormat = new SimpleDateFormat(gm);
inFormat.setLenient(false);
Date d = inFormat.parse(dateTime);
SimpleDateFormat outFormat = new SimpleDateFormat(strip
(yearSymbols, pattern));
outFormat.setTimeZone(timeZone);
return new XString(outFormat.format(d));
}
catch (ParseException pe)
{
}
try
{
SimpleDateFormat inFormat = new SimpleDateFormat(gd);
inFormat.setLenient(false);
Date d = inFormat.parse(dateTime);
SimpleDateFormat outFormat = new SimpleDateFormat(strip
(yearSymbols + monthSymbols, pattern));
outFormat.setTimeZone(timeZone);
return new XString(outFormat.format(d));
}
catch (ParseException pe)
{
}
return new XString("");
}
/**
* Strips occurrences of the given character from a date format pattern.
* @param symbols list of symbols to strip.
* @param pattern
* @return
*/
private static String strip(String symbols, String pattern)
{
int quoteSemaphore = 0;
int i = 0;
StringBuffer result = new StringBuffer(pattern.length());
while (i < pattern.length())
{
char ch = pattern.charAt(i);
if (ch == '\'')
{
// Assume it's an openening quote so simply copy the quoted
// text to the result. There is nothing to strip here.
int endQuote = pattern.indexOf('\'', i + 1);
if (endQuote == -1)
{
endQuote = pattern.length();
}
result.append(pattern.substring(i, endQuote));
i = endQuote++;
}
else if (symbols.indexOf(ch) > -1)
{
// The char needs to be stripped.
i++;
}
else
{
result.append(ch);
i++;
}
}
return result.toString();
}
----------->
And heres a JUnit test case.
<-----------
package org.apache.xalan.lib;
import java.util.TimeZone;
import junit.framework.TestCase;
import org.apache.xpath.objects.XString;
public class ExsltDatetimeTest extends TestCase
{
public ExsltDatetimeTest(String s)
{
super(s);
}
protected void setUp()
{
}
protected void tearDown()
{
}
public void testFormatDate()
{
// Set the default time zone so that the test runs correctly in all
// time zones.
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8:00"));
// Try a bunch of valid date combinations.
assertEquals(new XString("27 March 2003 14:22:12.0 GMT"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 March 2003 14:22:12.0 GMT+08:00"),
ExsltDatetime.formatDate("2003-03-27T14:22:12", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 March 2003 14:22:12.0 GMT"),
ExsltDatetime.formatDate("2003-03-27T14:22:12+00:00", "dd MMMM yyyy HH:mm:ss.S
z"));
assertEquals(new XString("27 March 2003 14:22:12.0 GMT"),
ExsltDatetime.formatDate("2003-03-27T14:22:12-00:00", "dd MMMM yyyy HH:mm:ss.S
z"));
assertEquals(new XString("27 March 2003 14:22:12.0 GMT+02:00"),
ExsltDatetime.formatDate("2003-03-27T14:22:12+02:00", "dd MMMM yyyy HH:mm:ss.S
z"));
assertEquals(new XString("27 March 2003 14:22:12.0 GMT-01:30"),
ExsltDatetime.formatDate("2003-03-27T14:22:12-01:30", "dd MMMM yyyy HH:mm:ss.S
z"));
assertEquals(new XString("27 March 2003 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("2003-03-27", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("01 March 2003 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("2003-03", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("01 January 2003 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("2003", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 March 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("--03-27", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("01 March 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("--03--", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 00:00:00.0 GMT+08:00"),
ExsltDatetime.formatDate("---27", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString(" 14:22:12.0 GMT+08:00"),
ExsltDatetime.formatDate("14:22:12", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 March 2003 HH:mm:ss.S GMT"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "dd MMMM yyyy 'HH:mm:ss.S'
z"));
assertEquals(new XString("27 March 2003 HH:mm:ss.S 14:22 GMT"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "dd MMMM yyyy 'HH:mm:ss.S'
HH:mm z"));
assertEquals(new XString("27 March 2003 '14:22:12.0"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "dd MMMM yyyy ''HH:mm:ss.S"));
// Try a few invalid ones.
assertEquals(new XString(""), ExsltDatetime.formatDate("this is not
even a date", "dd MMMM yyyy HH:mm:ss.S z"));
assertEquals(new XString("27 March 2003 HH:mm:ss.S"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "dd MMMM yyyy 'HH:mm:ss.S"));
assertEquals(new XString("dd MMMM yyyy HH:mm:ss.S z"),
ExsltDatetime.formatDate("2003-03-27T14:22:12Z", "'dd MMMM yyyy HH:mm:ss.S
z"));
assertEquals(new XString(""), ExsltDatetime.formatDate("2003-03-
27T14:22:12Z", ""));
assertEquals(new XString(""), ExsltDatetime.formatDate("", "dd MMMM
yyyy HH:mm:ss.S z"));
assertEquals(new XString(""), ExsltDatetime.formatDate("", ""));
// This test fails since SimpleDateFormat parses this as the year 0027
but
// then there is no recommendation about what to do when the input is
// invalid. At least it doesn't throw an exception.
//assertEquals(new XString(""), ExsltDatetime.formatDate("27 March
2003 00:00:00.0", "dd MMMM yyyy HH:mm:ss.S z"));
}
}
----------->