I started to look into the formatting of MMM, MMMM, EEE, and EEEE...
just a start. Hope it helps.
Regards,
Arvid
/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var DateFormatSymbols = Class.create();
DateFormatSymbols.prototype = {
initialize: function()
{
this.eras = new Array('BC', 'AD');
this.months = new Array('January', 'February', 'March', 'April',
'May', 'June', 'July', 'August', 'September', 'October',
'November', 'December', 'Undecimber');
this.shortMonths = new Array('Jan', 'Feb', 'Mar', 'Apr',
'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
'Nov', 'Dec', 'Und');
this.weekdays = new Array('Sunday', 'Monday', 'Tuesday',
'Wednesday', 'Thursday', 'Friday', 'Saturday');
this.shortWeekdays = new Array('Sun', 'Mon', 'Tue',
'Wed', 'Thu', 'Fri', 'Sat');
this.ampms = new Array('AM', 'PM');
this.zoneStrings = new Array(new Array(0, 'long-name', 'short-name'));
},
}
var SimpleDateFormatParserContext = Class.create();
SimpleDateFormatParserContext.prototype = {
initialize: function()
{
this.newIndex=0;
this.retValue=0;
this.year=0;
this.month=0;
this.day=0;
this.dayOfWeek=0;
this.hour=0;
this.min=0;
this.sec=0;
this.ampm=0;
this.dateStr="";
},
}
var SimpleDateFormat = Class.create();
SimpleDateFormat.prototype = {
initialize: function(pattern, dateFormatSymbols)
{
this.pattern = pattern;
this.dateFormatSymbols = dateFormatSymbols ? dateFormatSymbols : new
DateFormatSymbols();
},
_handle: function(dateStr, date, parse)
{
var patternIndex = 0;
var dateIndex = 0;
var commentMode = false;
var lastChar = 0;
var currentChar=0;
var nextChar=0;
var patternSub = null;
var context = new SimpleDateFormatParserContext();
if(date != null)
{
var yearStr = date.getYear()+"";
if (yearStr.length < 4)
{
yearStr=(parseInt(yearStr, 10)+1900)+"";
}
context.year = parseInt(yearStr, 10);
context.month = date.getMonth();
context.day = date.getDate();
context.dayOfWeek = date.getDay();
context.hour = date.getHours();
context.min = date.getMinutes();
context.sec = date.getSeconds();
}
while (patternIndex < this.pattern.length)
{
currentChar = this.pattern.charAt(patternIndex);
if(patternIndex<(this.pattern.length-1))
{
nextChar = this.pattern.charAt(patternIndex+1);
}
else
{
nextChar = 0;
}
if (currentChar == '\'' && lastChar!='\\')
{
commentMode = !commentMode;
patternIndex++;
}
else
{
if(!commentMode)
{
if (currentChar == '\\' && lastChar!='\\')
{
patternIndex++;
}
else
{
if(patternSub == null)
patternSub = "";
patternSub+=currentChar;
if(currentChar != nextChar)
{
this._handlePatternSub(context, patternSub,
dateStr, dateIndex, parse);
patternSub = null;
if(context.newIndex<0)
break;
dateIndex = context.newIndex;
}
patternIndex++;
}
}
else
{
if(parse)
{
if(this.pattern.charAt(patternIndex)!=dateStr.charAt(dateIndex))
{
//invalid character in dateString
return null;
}
}
else
{
context.dateStr+=this.pattern.charAt(patternIndex);
}
patternIndex++;
dateIndex++;
}
}
lastChar = currentChar;
}
this._handlePatternSub(context, patternSub,
dateStr, dateIndex, parse);
return context;
},
parse: function(dateStr)
{
var context = this._handle(dateStr, null, true);
return new Date(context.year, context.month,
context.day,context.hour,context.min,context.sec);
},
format: function(date)
{
var context = this._handle(null, date, false);
return context.dateStr;
},
parseString: function(context, dateStr, dateIndex, strings)
{
for(var i=0; i<strings.length;i++)
{
var currentStrings = strings[0];
for (var j = 0; j < currentStrings.length; j++)
{
var currentString = currentStrings[j];
if(dateStr.substring(dateIndex,dateIndex+currentString.length).equals(currentString))
{
context.newIndex=dateIndex+currentString.length;
context.retValue=j;
return context;
}
}
}
context.newIndex=-1;
return context;
},
_parseNum: function(context, dateStr, posCount, dateIndex)
{
for(var i=posCount;i>0;i--)
{
var numStr = dateStr.substring(dateIndex,dateIndex+posCount);
context.retValue = parseInt(numStr, 10);
if(context.retValue == Number.NaN)
continue;
context.newIndex = dateIndex+posCount;
return context;
}
context.newIndex = -1;
return context;
},
_handlePatternSub: function(context, patternSub, dateStr,
dateIndex, parse)
{
if(patternSub==null || patternSub.length==0)
return;
if(patternSub.charAt(0)=='y')
{
if(parse)
{
this._parseNum(context, dateStr,4,dateIndex);
context.year = context.retValue;
}
else
{
this._formatNum(context,context.year,patternSub.length);
}
}
else if(patternSub.charAt(0)=='M')
{
if(parse)
{
this._parseNum(context, dateStr,2,dateIndex);
context.month = context.retValue-1;
// XXX MMM, MMMM
}
else
{
if (patternSub.length == 3) {
context.dateStr +=
this.dateFormatSymbols.shortMonths[context.month];
} else if (patternSub.length >= 4) {
context.dateStr +=
this.dateFormatSymbols.months[context.month];
} else {
this._formatNum(context,context.month+1,patternSub.length);
}
}
}
else if(patternSub.charAt(0)=='d')
{
if(parse)
{
this._parseNum(context, dateStr,2,dateIndex);
context.day = context.retValue;
}
else
{
this._formatNum(context,context.day,patternSub.length);
}
}
else if(patternSub.charAt(0)=='E')
{
if(parse)
{
// XXX implement parse
this._parseNum(context, dateStr,2,dateIndex);
context.day = context.retValue;
}
else
{
if (patternSub.length <= 3) {
context.dateStr +=
this.dateFormatSymbols.shortWeekdays[context.dayOfWeek];
} else {
context.dateStr +=
this.dateFormatSymbols.weekdays[context.dayOfWeek];
}
}
}
else if(patternSub.charAt(0)=='H' ||
patternSub.charAt(0)=='h')
{
if(parse)
{
this._parseNum(context, dateStr,2,dateIndex);
context.hour = context.retValue;
}
else
{
this._formatNum(context,context.hour,patternSub.length);
}
}
else if(patternSub.charAt(0)=='m')
{
if(parse)
{
this._parseNum(context, dateStr,2,dateIndex);
context.min = context.retValue;
}
else
{
this._formatNum(context,context.min,patternSub.length);
}
}
else if(patternSub.charAt(0)=='s')
{
if(parse)
{
this._parseNum(context, dateStr,2,dateIndex);
context.sec = context.retValue;
}
else
{
this._formatNum(context,context.sec,patternSub.length);
}
}
else if(patternSub.charAt(0)=='a')
{
if(parse)
{
parseString(context, dateStr,dateIndex,new Array(ampms));
context.ampm = context.retValue;
}
else
{
this._formatNum(context,context.ampm,patternSub.length);
}
}
else
{
if(parse)
{
context.newIndex=dateIndex+patternSub.length;
}
else
{
context.dateStr+=patternSub;
}
}
},
_formatNum: function (context, num, length)
{
var str = num+"";
while(str.length<length)
str="0"+str;
context.dateStr+=str;
}
}import org.mozilla.javascript.JavaScriptException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Calendar;
import java.io.IOException;
public class DateTest extends JavaScriptTestCase {
protected void setUp() throws Exception {
super.setUp();
// loadScriptFile("debug.js");
loadScriptFile("prototype-basics.js");
loadScriptFile("date.js");
}
public void testNumberOnlyDateFormats() throws IOException,
JavaScriptException {
Date date = new Date();
String format = "yyyyMMdd";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format,
Locale.ENGLISH);
assertEquals(simpleDateFormat.format(date), evalDate(date, format));
format = "ddMMyyyy";
simpleDateFormat = new SimpleDateFormat(format, Locale.ENGLISH);
assertEquals(simpleDateFormat.format(date), evalDate(date, format));
}
public void testEnglishMonths() throws IOException {
for (int month = 0; month < 12; ++month) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, month);
Date date = calendar.getTime();
StringBuffer format = new StringBuffer("M");
for (int i = 0; i < 4; ++i) {
format.append('M');
SimpleDateFormat simpleDateFormat = new
SimpleDateFormat(format.toString(), Locale.ENGLISH);
assertEquals(simpleDateFormat.format(date), evalDate(date,
format.toString()));
}
}
}
public void testEnglishWeekDays() throws IOException {
for (int day = 1; day <= 7; ++day) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, day);
Date date = calendar.getTime();
StringBuffer format = new StringBuffer();
for (int i = 0; i < 3; ++i) {
format.append('E');
SimpleDateFormat simpleDateFormat = new
SimpleDateFormat(format.toString(), Locale.ENGLISH);
assertEquals(simpleDateFormat.format(date), evalDate(date,
format.toString()));
}
}
}
private Object evalDate(Date date, String format) {
return eval("new SimpleDateFormat(\"" + format + "\")"
+ ".format(new Date(" + date.getTime() + "))");
}
}