You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/01/02 17:48:13 UTC
svn commit: r608142 -
/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js
Author: skitching
Date: Wed Jan 2 08:48:05 2008
New Revision: 608142
URL: http://svn.apache.org/viewvc?rev=608142&view=rev
Log:
Major restructure/rewrite. This code is now a port of the java class org.apache.myfaces.dateformat.SimpleDateFormatter,
which has proper unit tests. This rewrite fixes a few bugs and adds support for "week of year" formats.
Modified:
myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js
Modified: myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js?rev=608142&r1=608141&r2=608142&view=diff
==============================================================================
--- myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js (original)
+++ myfaces/tomahawk/trunk/core/src/main/resources/org/apache/myfaces/custom/calendar/resource/date.js Wed Jan 2 08:48:05 2008
@@ -18,848 +18,921 @@
*/
//----------------------------------------------------------------------------
-// A javascript implementation of most of the java.text.SimpleDateFormat class,
-// written for the purposes of implementing the Apache MyFaces Tomahawk
-// calendar control.
+// This file contains a javascript implementation of most of the
+// java.text.SimpleDateFormat class, written for the purposes of implementing
+// the Apache MyFaces Tomahawk calendar control.
//
-// This file defines a javascript class, org_apache_myfaces_SimpleDateFormat.
+// This file defines a javascript class, org_apache_myfaces_dateformat_SimpleDateFormat.
// An instance of this class can be constructed, then used to parse strings
// into dates, and format dates into strings.
//
// Note that there is one difference from SimpleDateFormat in the formatting
-// string pattern; this code also supports the JODA "xxxx" pattern for weekYear.
-// If this is used, then the ugly java.text.SimpleDateFormat mangling of the
-// purpose of the "yyyy" pattern is disabled, allowing formatting patterns like
-// "xxxx-ww yyyy-mm-dd" to behave correctly.
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Return the week# represented by the specified date (1..53).
-//
-// This implements the ISO-8601 standard for week numbering, as documented in
-// Klaus Tondering's Calendar document, version 2.8:
-// http://www.tondering.dk/claus/calendar.html
-//
-// For dates in January and February, calculate:
-//
-// a = year-1
-// b = a/4 - a/100 + a/400
-// c = (a-1)/4 - (a-1)/100 + (a-1)/400
-// s = b-c
-// e = 0
-// f = day - 1 + 31*(month-1)
-//
-// For dates in March through December, calculate:
-//
-// a = year
-// b = a/4 - a/100 + a/400
-// c = (a-1)/4 - (a-1)/100 + (a-1)/400
-// s = b-c
-// e = s+1
-// f = day + (153*(month-3)+2)/5 + 58 + s
-//
-// Then, for any month continue thus:
-//
-// g = (a + b) mod 7
-// d = (f + g - e) mod 7
-// n = f + 3 - d
-//
-// We now have three situations:
-//
-// If n<0, the day lies in week 53-(g-s)/5 of the previous year.
-// If n>364+s, the day lies in week 1 of the coming year.
-// Otherwise, the day lies in week n/7 + 1 of the current year.
-//
-// This algorithm gives you a couple of additional useful values:
-//
-// d indicates the day of the week (0=Monday, 1=Tuesday, etc.)
-// f+1 is the ordinal number of the date within the current year.
+// string pattern; this code optionally supports ISO-8601 weeks, and the JODA
+// "xxxx" pattern for weekYear.
//
-// Note that ISO-8601 specifies that week1 of a year is the first week in
-// which the majority of days lie in that year. An equivalent description
-// is that it is the first week including the 4th of january. This means
-// that the 1st, 2nd and 3rd of January might lie in the last week of the
-// previous year, and that the last week of a year may include the first
-// few days of the following year.
-//
-// ISO-8601 also specifies that the first day of the week is always Monday.
-//
-// This function returns the week number regardless of which year it lies in.
-// That means that asking for the week# of 01/01/yyyy might return 52 or 53,
-// and asking for the week# of 31/12/yyyy might return 1.
+// This code is a "port" of java class org.apache.myfaces.dateformat.SimpleDateFormatter
+// from Apache Myfaces Tomahawk, with the minimum number of changes needed to
+// make the code work in javascript. See that class for further documentation
+// about the code in this file. Any "fixes" needed in the code below should
+// first be implemented (and tested) in the base java version.
+//
+// The main differences between the java code and this javascript are that
+// in java a lot of methods are declared static to ensure they do not
+// accidentally change the object state. But this is very inconvenient to
+// do in javascript as static function names must include the "namespace"
+// prefix, eg org_apache_myfaces_dateformat_SimpleDateFormatter_foo().
+// Instead, all these methods are implemented as non-static member methods.
+// In addition, private methods have an underscore added to the start of
+// the name. Note also that the constructor for a java.util.Date object takes
+// a year relative to 1900, while javascript takes one relative to 0AD.
//----------------------------------------------------------------------------
-function org_apache_myfaces_SimpleDateFormat_weekNbr(n)
+
+// Constructor for DateFormatSymbols class
+org_apache_myfaces_dateformat_DateFormatSymbols = function()
{
- var year = n.getFullYear();
- var month = n.getMonth() + 1;
- var day = n.getDate();
-
- var a,b,c,d,e,f,g;
-
- if (month <= 2)
- {
- a = year - 1;
- b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
- c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
- s = b - c;
- e = 0;
- f = day - 1 + 31*(month-1);
- }
- else
- {
- a = year;
- b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
- c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
- s = b - c;
- e = s + 1;
- f = day + Math.floor((153*(month-3) + 2)/5) + 58 + s;
- }
+ 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 threshold = new Date();
+ threshold.setYear(threshold.getYear()-80);
+ this.twoDigitYearStart = threshold;
+}
- g = (a + b) % 7;
- d = (f + g - e) % 7;
- n = f + 3 - d;
+// Constructor for ParserContext class
+org_apache_myfaces_dateformat_ParserContext = function(dow)
+{
+ this.newIndex=0;
+ this.invalid = false;
+ this.firstDayOfWeek = dow;
+ this.ambigousYear=false;
+ this.ambigousWeekYear=false;
+
+ this.year=0;
+ this.month=0;
+ this.day=1;
+ this.dayOfWeek=0;
+ this.hour=0;
+ this.hourAmpm;
+ this.min=0;
+ this.sec=0;
+ this.ampm=0;
+
+ this.weekYear=0;
+ this.weekOfWeekYear=0;
+}
- var week;
- if (n<0)
- {
- // previous year
- week = 53 - Math.floor((g-s)/5);
- }
- else if (n > (364+s))
- {
- // next year
- week = 1;
- }
- else
- {
- // current year
- week = Math.floor(n/7) + 1;
- }
-
- return week;
+// constructor for WeekDate class
+org_apache_myfaces_dateformat_WeekDate = function(year, week)
+{
+ this.year = year;
+ this.week = week;
}
-//----------------------------------------------------------------------------
-// Create a new date using "week in year" rather than "month in year".
-// Weeks always begin on a monday (ISO-8601).
-//
-// This functions like
-// new Date(year,month,day,hour,min,sec)
-// except that week (1..53) is used in place of month, and day is (1..7), not
-// 1..31.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat_newDateByWeekYear = function(year, week, day, hour, min, sec)
+// constructor for StringBuffer class
+org_apache_myfaces_dateformat_StringBuffer = function(s)
{
- var MSECS_PER_DAY = 24*60*60*1000;
-
- var date = new Date(
- year, 0, 1,
- hour, min, sec);
-
- // Nudge date to the nearest Monday from the start of the year;
- // weeks always start on a monday. Note that it might be in the
- // previous year. The actual date for the start of the first week
- // in the year is guaranteed to be in the range (29dec-4jan)
- var dow = date.getDay();
- var daysOffset;
- if (dow == 1)
- {
- // first day of year is monday, so no offset needed.
- daysOffset = 0;
- }
- else if (dow <= 4)
- {
- // first day-of-year is tue, wed, thurs so the nearest monday is
- // earlier (in the previous year). The offset will be negative.
- daysOffset = 1 - dow;
- }
- else
- {
- // first day-of-year is fri,sat,sun so the nearest monday
- // is later..
- daysOffset = 8 - dow;
- }
-
- // now add week*7 days
- daysOffset += (week - 1) * 7 + (day - 1);
+ if (s == null)
+ this.str = "";
+ else
+ this.str = s;
+
+ var proto = org_apache_myfaces_dateformat_StringBuffer.prototype;
+ proto.append = function(s)
+ {
+ this.str = this.str + s;
+ }
+
+ proto.toString = function()
+ {
+ return this.str;
+ }
+}
- // do arithmetic
- var msecsBase = date.getTime();
- var msecsOffset = daysOffset * MSECS_PER_DAY;
-
- var finalDate = new Date();
- finalDate.setTime(msecsBase + msecsOffset);
- return finalDate;
+// Constructor for SimpleDateFormatter class
+org_apache_myfaces_dateformat_SimpleDateFormatter = function(pattern, symbols, firstDayOfWeek)
+{
+ this._construct(pattern, symbols, firstDayOfWeek);
}
-//----------------------------------------------------------------------------
-// Constructor for a simple object that contains locale-specific constants
-// used for date parsing and formatting.
-//----------------------------------------------------------------------------
-org_apache_myfaces_DateFormatSymbols = function()
+// static initialisation block; requires constructor for SimpleDateFormatter
+// to run first in order to create the prototype object that this block
+// attaches methods and constants to.
{
- 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 threshold = new Date();
- threshold.setYear(threshold.getYear()-80);
- this.twoDigitYearStart = threshold;
+var proto = org_apache_myfaces_dateformat_SimpleDateFormatter.prototype;
+
+proto.MSECS_PER_SEC = 1000;
+proto.MSECS_PER_MIN = 60 * proto.MSECS_PER_SEC;
+proto.MSECS_PER_HOUR = 60 * proto.MSECS_PER_MIN;
+proto.MSECS_PER_DAY = 24 * proto.MSECS_PER_HOUR;
+proto.MSECS_PER_WEEK = 7 * proto.MSECS_PER_DAY;
+
+proto.MONTH_LEN =
+[
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+];
+
+proto._getIsoWeekDate = function(date)
+{
+ var year = date.getFullYear();
+ var month = date.getMonth() + 1;
+ var day = date.getDate();
+
+ var a,b,c,d,e,f,g,s,n;
+
+ if (month <= 2)
+ {
+ a = year - 1;
+ b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
+ c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
+ s = b - c;
+ e = 0;
+ f = day - 1 + 31*(month-1);
+ }
+ else
+ {
+ a = year;
+ b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
+ c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
+ s = b - c;
+ e = s + 1;
+ f = day + Math.floor((153*(month-3) + 2)/5) + 58 + s;
+ }
+
+ g = (a + b) % 7;
+ d = (f + g - e) % 7;
+ n = f + 3 - d;
+
+ if (n<0)
+ {
+ // previous year
+ var resultWeek = 53 - Math.floor((g-s)/5);
+ return new org_apache_myfaces_dateformat_WeekDate(year-1, resultWeek);
+ }
+ else if (n > (364+s))
+ {
+ // next year
+ var resultWeek = 1;
+ return new org_apache_myfaces_dateformat_WeekDate(year+1, resultWeek);
+ }
+ else
+ {
+ // current year
+ var resultWeek = Math.floor(n/7) + 1;
+ return new org_apache_myfaces_dateformat_WeekDate(year, resultWeek);
+ }
}
-//----------------------------------------------------------------------------
-// Constructor for a simple object that contains the current parsing or
-// formatting state. This encapsulates the properties of a SimpleDateFormat
-// which are modified during a parse or format call.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormatParserContext = function()
+proto._isLeapYear = function(year)
{
- this.newIndex=0;
- this.retValue=0;
- this.year=0;
- this.ambigousYear=false;
- this.month=0;
- this.day=0;
- this.dayOfWeek=0;
- this.hour=0;
- this.min=0;
- this.sec=0;
- this.ampm=0;
- this.dateStr="";
-
- this.weekYear=0;
- this.weekOfWeekYear=0;
- this.yearIsWeekYear=false;
+ return ((year%4 == 0) && (year%100 != 0)) || (year%400 == 0);
}
-//----------------------------------------------------------------------------
-// Constructor method.
-//
-// param pattern defines the pattern to be used for parsing or formatting.
-//
-// param dateSymbols is optional. It defines the "locale"; if not defined
-// then default settings (english locale) are used.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat = function(pattern, dateFormatSymbols)
+proto._dayOfWeek = function(year, month, day)
{
- this.pattern = pattern;
- this.dateFormatSymbols = dateFormatSymbols ? dateFormatSymbols :
- new org_apache_myfaces_DateFormatSymbols();
+ month -= 2;
+ if (month < 1)
+ {
+ month += 12;
+ --year;
+ }
+
+ var cent = Math.floor(year / 100);
+ year %= 100;
+
+ var base =
+ Math.floor((26 * month - 2) / 10)
+ + day
+ + year
+ + Math.floor(year/4)
+ + Math.floor(cent/4)
+ + (5*cent);
+
+ var dow = base % 7;
+ return dow;
}
-//----------------------------------------------------------------------------
-// Handle both parsing and formatting of dates, by walking the pattern and
-// invoking _handlePatternSub for each "segment" of the pattern.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._handle = function(dateStr, date, parse)
+proto._getJavaWeekDate = function(date, firstDayOfWeek)
+{
+ var year = date.getFullYear();
+ var month = date.getMonth() + 1;
+ var day = date.getDate();
+
+ var thisIsLeapYear = this._isLeapYear(year);
+
+ var dayOfYear = day + this.MONTH_LEN[month-1];
+ if (thisIsLeapYear && (month>2))
+ {
+ ++dayOfYear;
+ }
+
+ var jan1Weekday = this._dayOfWeek(year, 1, 1);
+
+ var pivotOffset = firstDayOfWeek - jan1Weekday;
+ if (pivotOffset > 3)
+ {
+ pivotOffset -= 7;
+ }
+ else if (pivotOffset < -3)
+ {
+ pivotOffset += 7;
+ }
+
+ var dayOffset = dayOfYear-1;
+ if (dayOffset < pivotOffset)
+ {
+ var prevIsLeapYear = this._isLeapYear(year-1);
+ if ((pivotOffset==3) || ((pivotOffset==2) && prevIsLeapYear))
{
- var patternIndex = 0;
- var commentMode = false;
- var lastChar = 0;
- var currentChar=0;
- var nextChar=0;
- var patternSub = null;
- var ops = [];
- var i;
- var controls="yxMdEHhmsaw";
- var wwPresent = false;
- var xxPresent = false;
-
- var context = new org_apache_myfaces_SimpleDateFormatParserContext();
-
- if(date != null)
- {
- context.year = this._fullYearFromDate(date.getYear());
- context.month = date.getMonth();
- context.day = date.getDate();
- context.dayOfWeek = date.getDay();
- context.hour = date.getHours();
- context.min = date.getMinutes();
- context.sec = date.getSeconds();
-
- context.weekOfWeekYear = this._weekNbr(date);
- if ((context.weekOfWeekYear > 50) && (context.month==0))
- context.weekYear = context.year - 1;
- else if ((context.weekOfWeekYear == 1) && (context.month==12))
- context.weekYear = context.year + 1;
- else
- context.weekYear = context.year;
- }
-
-
- // Walk through the date pattern char by char, splitting it up into
- // "comment segments", "pattern segments" and "literal segments".
- 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!='\\')
- {
- if (patternSub != null)
- {
- this._append(ops, patternSub);
- patternSub = null;
- }
- commentMode = !commentMode;
- }
- else if (commentMode)
- {
- if (patternSub == null)
- {
- patternSub = "c:";
- }
- patternSub += currentChar;
- }
- else
- {
- if (currentChar == '\\' && lastChar!='\\')
- {
- }
- else
- {
- if(patternSub == null)
- {
- if (controls.indexOf(currentChar)<0)
- patternSub = "l:";
- else
- patternSub = "f:";
- }
- patternSub+=currentChar;
- if(currentChar != nextChar)
- {
- this._append(ops, patternSub);
- patternSub = null;
- }
-
- }
- }
-
- patternIndex++;
- lastChar = currentChar;
- }
-
- if (patternSub != null)
- this._append(ops, patternSub);
-
- // Ugly hack to make the "yyyy" formatter behave differently if the
- // "ww" formatter is also present in the pattern. This is what
- // java.text.SimpleDateFormat does. The JODA library implements
- // an "xxxx" formatter instead, and allows "yyyy" to behave normally;
- // this is nicer so support that if formatter "xx" is present.
- for(i=0;i<ops.length;++i)
- {
- var s = ops[i];
- wwPresent = wwPresent || ("f:ww" == s.substr(0,4));
- xxPresent = xxPresent || ("f:xx" == s.substr(0,4));
- }
- context.yearIsWeekYear = wwPresent && !xxPresent;
-
- if (parse)
- context = this._parseOps(context, ops, dateStr);
- else
- context = this._formatOps(context, ops);
-
- return context;
- };
-
-org_apache_myfaces_SimpleDateFormat.prototype._parseOps = function(context, ops, dateStr)
-{
- var dateIndex = 0;
- var i;
- for(i=0;i<ops.length;++i)
- {
- var op = ops[i];
- var optype = op.substr(0,2);
- var opval = op.substr(2);
- if (optype == "f:")
- {
- this._handlePatternSub(context, opval,
- dateStr, dateIndex, true);
-
- if(context.newIndex<0)
- break;
-
- dateIndex = context.newIndex;
- }
- else if (optype == "l:")
- {
- // Just skip over the equivalent number of chars. This is what the previous
- // parsing implementation did...
- dateIndex += opval.length;
- }
- else if (optype == "c:")
- {
- // verify that opval matches the next chars in dateStr, then
- // advance dateIndex by the length.
- var s = dateStr.substr(dateIndex, opval.length);
- if (s != opval)
- {
- context.retValue = -1;
- break;
- }
- dateIndex += opval.length;
- }
+ return new org_apache_myfaces_dateformat_WeekDate(year-1, 53);
}
-
- return context;
+ return new org_apache_myfaces_dateformat_WeekDate(year-1, 52);
+ }
+
+ var daysFromFirstWeekStart = (dayOfYear - 1 - pivotOffset);
+ var weekNumber = Math.floor(daysFromFirstWeekStart/7) + 1;
+
+ if ((weekNumber < 53)
+ || (pivotOffset == -3)
+ || (pivotOffset == -2 && thisIsLeapYear))
+ {
+ return new org_apache_myfaces_dateformat_WeekDate(year, weekNumber);
+ }
+ else
+ {
+ return new org_apache_myfaces_dateformat_WeekDate(year+1, 1);
+ }
}
-org_apache_myfaces_SimpleDateFormat.prototype._formatOps = function(context, ops)
+proto._getStartOfWeekYear = function(year, firstDayOfWeek)
{
- var dateIndex = 0; // not used on formatting, only on parsing
- var dateStr = ""; // not used on formatting, only on parsing
- var i;
- for(i=0;i<ops.length;++i)
- {
- var op = ops[i];
- var optype = op.substr(0,2);
- var opval = op.substr(2);
- if (optype == "f:")
- {
- this._handlePatternSub(context, opval,
- dateStr, dateIndex, false);
- }
- else if (optype == "l:")
- {
- // just output the literal sequence into the result
- context.dateStr += opval;
- }
- else if (optype == "c:")
- {
- // just output the literal sequence into the result
- context.dateStr += opval;
- }
- }
-
- return context;
+ var d1 = new Date(year, 0, 1, 0, 0, 0);
+ var firstDayOfYear = d1.getDay();
+ var dayDiff = firstDayOfWeek - firstDayOfYear;
+ var dayShift;
+ if (dayDiff >= 4)
+ {
+ dayShift = 7 - dayShift;
+ }
+ else if (dayDiff >= 0)
+ {
+ dayShift = dayDiff;
+ }
+ else if (dayDiff >= -3)
+ {
+ dayShift = dayDiff;
+ }
+ else
+ {
+ dayShift = 7 + dayDiff;
+ }
+
+ var weekYearStartMsecs = d1.getTime() + (dayShift * this.MSECS_PER_DAY);
+ return weekYearStartMsecs;
}
-//----------------------------------------------------------------------------
-// Parse a string using the configured pattern, and return a normal javascript
-// Date object.
-//
-// Returns null if parsing failed.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype.parse = function(dateStr)
- {
- if(!dateStr || dateStr.length==0)
- return null;
+proto._newJavaDateByWeekYear = function(
+ year, week, day,
+ hour, min, sec,
+ firstDayOfWeek)
+{
+ var msecsBase = this._getStartOfWeekYear(year, firstDayOfWeek);
+ var msecsOffset = (week-1) * this.MSECS_PER_WEEK;
+ msecsOffset += (day-1) * this.MSECS_PER_DAY;
+ msecsOffset += hour * this.MSECS_PER_HOUR;
+ msecsOffset += min * this.MSECS_PER_MIN;
+ msecsOffset += sec * this.MSECS_PER_SEC;
+
+ var finalDate = new Date();
+ finalDate.setTime(msecsBase + msecsOffset);
+ return finalDate;
+}
- var context = this._handle(dateStr, null, true);
+proto._fullYearFromDate = function(year)
+{
+ if (year < 1900)
+ {
+ return year+1900;
+ }
+ else
+ {
+ return year;
+ }
+}
- if(context.retValue==-1)
- return null;
+proto._createDateFromContext = function(context)
+{
+ var date;
+ if (context.weekOfWeekYear != 0)
+ {
+ date = this._newJavaDateByWeekYear(
+ context.weekYear, context.weekOfWeekYear, context.day,
+ context.hour, context.min, context.sec,
+ context.firstDayOfWeek);
+ }
+ else
+ {
+ date = new Date(
+ context.year, context.month, context.day,
+ context.hour, context.min, context.sec);
+ }
+ return date;
+}
- this._adjustTwoDigitYear(context);
+proto._substr = function(s, start, len)
+{
+ var s2 = s.substring(start);
+ if (s2.length <= len)
+ return s2;
+ else
+ return s2.substring(0, len);
+}
- return this._createDateFromContext(context);
- };
+proto._parseOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, dateStr)
+{
+ var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._createDateFromContext=function(context)
+ var dateIndex = 0;
+ var dateStrLen = dateStr.length;
+ for(var i=0; (i<ops.length) && (dateIndex < dateStrLen); ++i)
+ {
+ var op = ops[i];
+ var optype = op.substring(0, 2);
+ var opval = op.substring(2);
+
+ if (optype == "f:")
{
- var date;
- if (context.weekOfWeekYear != 0)
- {
- date = org_apache_myfaces_SimpleDateFormat_newDateByWeekYear(
- context.weekYear, context.weekOfWeekYear, context.day,
- context.hour, context.min, context.sec);
- }
- else
- {
- date = new Date(
- context.year, context.month, context.day,
- context.hour,context.min,context.sec);
- }
- return date;
- };
+ this._parsePattern(symbols, yearIsWeekYear, context, opval, dateStr, dateIndex);
-//----------------------------------------------------------------------------
-// Accept a normal javascript Date object, and return a String.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype.format = function(date)
+ if ((context.newIndex < 0) || context.invalid)
+ break;
+
+ dateIndex = context.newIndex;
+ }
+ else if (optype =="q:" || optype == "l:")
{
- var context = this._handle(null, date, false);
+ var oplen = opval.length;
+ var s = this._substr(dateStr, dateIndex, oplen);
+ if (opval != s)
+ {
+ context.invalid = true;
+ break;
+ }
+ dateIndex += oplen;
+ }
+ }
- return context.dateStr;
- };
+ return context;
+}
-//----------------------------------------------------------------------------
-// dateStr is the full string currently being parsed.
-// dateIndex is the offset within dateStr to parse from.
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._parseString = function(context, dateStr, dateIndex, strings)
+proto._parsePattern = function(
+ symbols, yearIsWeekYear, context, patternSub, dateStr, dateIndex)
+{
+ var c = patternSub.charAt(0);
+ var patlen = patternSub.length;
+
+ if (c == 'y')
+ {
+ var year = this._parseNum(context, dateStr, 4, dateIndex);
+ if ((context.newIndex-dateIndex) < 4)
+ {
+ context.year = year;
+ context.ambiguousYear = true;
+ }
+ else
{
- var fragment = dateStr.substr(dateIndex);
- var index = this._prefixOf(strings, fragment);
- if (index != -1) {
- context.retValue = index;
- context.newIndex = dateIndex + strings[index].length;
- return context;
- }
-
- context.retValue=-1;
- context.newIndex=-1;
- return context;
- };
+ context.year = year;
+ }
-//----------------------------------------------------------------------------
-// Convert at most the next posCount characters to numeric (or stop at
-// end-of-string), starting from offset dateIndex within dateStr.
-//
-// dateStr is the full string currently being parsed.
-// dateIndex is the offset within dateStr to parse from.
-//
-// Stores the result in context.retValue
-// Updates context.newIndex to contain the next unparsed char within dateStr
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._parseNum = function(context, dateStr, posCount, dateIndex)
+ if (yearIsWeekYear)
+ {
+ // There is a "ww" pattern present, so set weekYear as well as year.
+ context.weekYear = context.year;
+ context.ambiguousWeekYear = context.ambiguousYear;
+ }
+ }
+ else if (c == 'x')
+ {
+ // extension to standard java.text.SimpleDateFormat class, to support the
+ // JODA "weekYear" formatter.
+ var year = this._parseNum(context, dateStr, 4, dateIndex);
+ if ((context.newIndex-dateIndex) < 4)
+ {
+ context.weekYear = year;
+ context.ambiguousWeekYear = true;
+ }
+ else
+ {
+ context.weekYear = year;
+ }
+ }
+ else if (c == 'M')
+ {
+ if (patlen == 3)
+ {
+ var fragment = this._substr(dateStr, dateIndex, 3);
+ var index = this._parseIndexOf(context, symbols.shortMonths, fragment);
+ if (index != -1)
+ {
+ context.month = index;
+ }
+ }
+ else if (patlen >= 4)
+ {
+ var fragment = dateStr.substring(dateIndex);
+ var index = this._parsePrefixOf(context, symbols.months, fragment);
+ if (index != -1)
+ {
+ context.month = index;
+ }
+ }
+ else
{
- // Try to convert the most possible characters (posCount). If that fails,
- // then try again without the last character. Repeat until successful
- // numeric conversion occurs.
- for(var i=Math.min(posCount,dateStr.length-dateIndex);i>0;i--)
- {
- var numStr = dateStr.substring(dateIndex,dateIndex+i);
-
- context.retValue = this._parseInt(numStr);
-
- if(context.retValue == -1)
- continue;
-
- context.newIndex = dateIndex+i;
- return context;
- }
-
- context.retValue = -1;
- context.newIndex = -1;
- return context;
- };
+ context.month = this._parseNum(context, dateStr, 2, dateIndex) - 1;
+ }
+ }
+ else if (c == 'd')
+ {
+ context.day = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else if (c == 'E')
+ {
+ if (patlen <= 3)
+ {
+ var fragment = dateStr.substring(dateIndex, dateIndex+3);
+ var index = this._parseIndexOf(context, symbols.shortWeekdays, fragment);
+ if (index != -1)
+ {
+ context.dayOfWeek = index;
+ }
+ }
+ else
+ {
+ var fragment = dateStr.substring(dateIndex);
+ var index = this._parsePrefixOf(context, symbols.weekdays, fragment);
+ if (index != -1)
+ {
+ context.dayOfWeek = index;
+ }
+ }
+ }
+ else if (c == 'H')
+ {
+ context.hour = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else if (c == 'h')
+ {
+ context.hourAmpm = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else if (c == 'm')
+ {
+ context.min = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else if (c == 's')
+ {
+ context.sec = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else if (c == 'a')
+ {
+ context.ampm = this._parseString(context, dateStr, dateIndex, symbols.ampms);
+ }
+ else if (c == 'w')
+ {
+ context.weekOfWeekYear = this._parseNum(context, dateStr, 2, dateIndex);
+ }
+ else
+ {
+ context.invalid = true;
+ }
+}
-//----------------------------------------------------------------------------
-// Handles a "segment" of a pattern, for either parsing or formatting.
-//
-// patternSub contains a sequence of identical chars, eg "yyyy" or "HH".
-// returns VOID
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._handlePatternSub = function(context, patternSub, dateStr, dateIndex, parse)
+proto._parseInt = function(value)
+{
+ var sum = 0;
+ for(var i=0;i<value.length;i++)
+ {
+ var c = value.charAt(i);
+
+ if(c<'0'||c>'9')
{
- if(patternSub==null || patternSub.length==0)
- return;
+ return -1;
+ }
+ sum = sum*10+(c-'0');
+ }
+ return sum;
+}
- if(patternSub.charAt(0)=='y')
- {
- if(parse)
- {
- this._parseNum(context, dateStr,4,dateIndex);
-
- if((context.newIndex-dateIndex)<4)
- {
- context.year = context.retValue+1900;
- context.ambigousYear = true;
- }
- else
- {
- context.year = context.retValue;
- }
-
- if (context.yearIsWeekYear)
- context.weekYear = context.year;
- }
- else
- {
- if (context.yearIsWeekYear)
- this._formatNum(context,context.weekYear,patternSub.length <= 3 ? 2 : 4,true);
- else
- this._formatNum(context,context.year,patternSub.length <= 3 ? 2 : 4,true);
- }
- }
- else if(patternSub.charAt(0)=='x')
- {
- if(parse)
- {
- this._parseNum(context, dateStr,4,dateIndex);
-
- if((context.newIndex-dateIndex)<4)
- {
- context.weekYear = context.retValue+1900;
- context.ambigousYear = true;
- }
- else
- {
- context.weekYear = context.retValue;
- }
- }
- else
- {
- this._formatNum(context,context.weekYear,patternSub.length <= 3 ? 2 : 4,true);
- }
- }
- else if(patternSub.charAt(0)=='M')
- {
- if(parse)
- {
- if (patternSub.length == 3) {
- var fragment = dateStr.substr(dateIndex, 3);
- var index = this._indexOf(this.dateFormatSymbols.shortMonths, fragment);
- if (index != -1) {
- context.month = index;
- context.newIndex = dateIndex + 3;
- }
- } else if (patternSub.length >= 4) {
- var fragment = dateStr.substr(dateIndex);
- var index = this._prefixOf(this.dateFormatSymbols.months, fragment);
- if (index != -1) {
- context.month = index;
- context.newIndex = dateIndex + this.dateFormatSymbols.months[index].length;
- }
- } else {
- this._parseNum(context, dateStr,2,dateIndex);
- context.month = context.retValue-1;
- }
- }
- 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 dayOfWeek is not used to generate date at the moment
- if (patternSub.length <= 3) {
- var fragment = dateStr.substr(dateIndex, 3);
- var index = this._indexOf(this.dateFormatSymbols.shortWeekdays, fragment);
- if (index != -1) {
- context.dayOfWeek = index;
- context.newIndex = dateIndex + 3;
- }
- } else {
- var fragment = dateStr.substr(dateIndex);
- var index = this._prefixOf(this.dateFormatSymbols.weekdays, fragment);
- if (index != -1) {
- context.dayOfWeek = index;
- context.newIndex = dateIndex + this.dateFormatSymbols.weekdays[index].length;
- }
- }
- }
- 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)
- {
- this._parseString(context, dateStr,dateIndex,this.dateFormatSymbols.ampms);
- context.ampm = context.retValue;
- }
- else
- {
- context.dateStr += this.dateFormatSymbols.ampms[context.ampm];
- }
- }
- else if(patternSub.charAt(0)=='w')
- {
- if(parse)
- {
- this._parseNum(context, dateStr,2,dateIndex);
- context.weekOfWeekYear = context.retValue;
- }
- else
- {
- this._formatNum(context,context.weekOfWeekYear,patternSub.length);
- }
- }
- else
- {
- if(parse)
- {
- // just skip over it
- context.newIndex=dateIndex+patternSub.length;
- }
- else
- {
- // just copy it to the output
- context.dateStr+=patternSub;
- }
+proto._parseNum = function(context, dateStr, nChars, dateIndex)
+{
+ // Try to convert the most possible characters (posCount). If that fails,
+ // then try again without the last character. Repeat until successful
+ // numeric conversion occurs.
+ var nToParse = Math.min(nChars, dateStr.length - dateIndex);
+ for(var i=nToParse;i>0;i--)
+ {
+ var numStr = dateStr.substring(dateIndex,dateIndex+i);
+ var value = this._parseInt(numStr);
+ if(value == -1)
+ continue;
+
+ context.newIndex = dateIndex+i;
+ return value;
+ }
+
+ context.newIndex = -1;
+ context.invalid = true;
+ return -1;
+}
- }
- };
+proto._parseIndexOf = function(context, array, value)
+{
+ for (var i = 0; i < array.length; ++i)
+ {
+ var s = array[i];
+ if (value == s)
+ {
+ context.newIndex += s.length;
+ return i;
+ }
+ }
+ context.invalid = true;
+ context.newIndex = -1;
+ return -1;
+}
-//----------------------------------------------------------------------------
-// Write out an integer padded with leading zeros to a specified width
-// If ensureLength is set, and the number is longer than length, then display only the rightmost length digits.
-//
-// modifies member variable context.dateStr, returns VOID
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._formatNum = function (context, num, length, ensureLength)
+proto._parsePrefixOf = function(context, array, value)
+{
+ for (var i=0; i <array.length; ++i)
+ {
+ var s = array[i];
+ if (value.indexOf(s) == 0)
{
- var str = num+"";
+ context.newIndex += s.length;
+ return i;
+ }
+ }
+ context.invalid = true;
+ context.newIndex = -1;
+ return -1;
+}
- while(str.length<length)
- str="0"+str;
+proto._parseString = function(context, dateStr, dateIndex, strings)
+{
+ var fragment = dateStr.substr(dateIndex);
+ return this._parsePrefixOf(context, strings, fragment);
+}
- // XXX do we have to distinguish left and right 'cutting'
- //ensureLength - enable cutting only for parameters like the year, the other
- if (ensureLength && str.length > length) {
- str = str.substr(str.length - length);
- }
+proto._parsePostProcess = function(symbols, context)
+{
+ if (context.ambiguousYear)
+ {
+ var date = this._createDateFromContext(context);
+ var threshold = symbols.twoDigitYearStart;
+ if (date.getTime() < threshold.getTime())
+ {
+ context.year += 100;
+ }
+ }
+
+ if (context.hourAmpm > 0)
+ {
+ if (context.ampm == 1)
+ {
+ context.hour = context.hourAmpm + 12;
+ if (context.hour == 24)
+ context.hour = 0;
+ }
+ else
+ {
+ context.hour = context.hourAmpm;
+ }
+ }
+}
- context.dateStr+=str;
- };
+proto._formatOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, date)
+{
+ var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
- // perhaps add to Array.prototype
-org_apache_myfaces_SimpleDateFormat.prototype._indexOf = function (array, value)
+ context.year = date.getFullYear();
+ context.month = date.getMonth();
+ context.day = date.getDate();
+ context.dayOfWeek = date.getDay();
+ context.hour = date.getHours();
+ context.min = date.getMinutes();
+ context.sec = date.getSeconds();
+
+ context.ampm = (context.hour < 12) ? 0 : 1;
+
+ var weekDate = this._getJavaWeekDate(date, firstDayOfWeek);
+ context.weekYear = weekDate.year;
+ context.weekOfWeekYear = weekDate.week;
+
+ var str = new org_apache_myfaces_dateformat_StringBuffer();
+ for(var i=0; i<ops.length; ++i)
+ {
+ var op = ops[i];
+ var optype = op.substring(0, 2);
+ var opval = op.substring(2);
+
+ if (optype == "f:")
+ {
+ this._formatPattern(symbols, context, opval, yearIsWeekYear, str);
+ if (context.invalid)
+ break;
+ }
+ else if (optype == "l:")
{
- for (var i = 0; i < array.length; ++i) {
- if (array[i] == value) {
- return i;
- }
- }
- return -1;
- };
-
-org_apache_myfaces_SimpleDateFormat.prototype._prefixOf = function (array, value)
+ str.append(opval);
+ }
+ else if (optype == "q:")
{
- for (var i = 0; i < array.length; ++i) {
- if (value.indexOf(array[i]) == 0) {
- return i;
- }
- }
- return -1;
- };
+ str.append(opval);
+ }
+ }
+
+ if (context.invalid)
+ return null;
+ else
+ return str.toString();
+}
+
+proto._formatPattern = function(
+ symbols, context, patternSub, yearIsWeekYear, out)
+{
+ var c = patternSub.charAt(0);
+ var patlen = patternSub.length;
-org_apache_myfaces_SimpleDateFormat.prototype._parseInt = function(value)
+ if (c=='y')
+ {
+ if (!yearIsWeekYear)
+ this._formatNum(context.year, patlen <= 3 ? 2 : 4, true, out);
+ else
+ this._formatNum(context.weekYear, patlen <= 3 ? 2 : 4, true, out);
+ }
+ else if (c=='x')
+ {
+ this._formatNum(context.weekYear,patlen <= 3 ? 2 : 4, true, out);
+ }
+ else if (c=='M')
+ {
+ if (patlen == 3)
+ {
+ out.append(symbols.shortMonths[context.month]);
+ }
+ else if (patlen >= 4) {
+ out.append(symbols.months[context.month]);
+ }
+ else
+ {
+ this._formatNum(context.month+1,patlen, false, out);
+ }
+ }
+ else if (c=='d')
+ {
+ this._formatNum(context.day,patlen, false, out);
+ }
+ else if (c=='E')
+ {
+ if (patlen <= 3)
+ {
+ out.append(symbols.shortWeekdays[context.dayOfWeek]);
+ }
+ else
+ {
+ out.append(symbols.weekdays[context.dayOfWeek]);
+ }
+ }
+ else if(c=='H')
+ {
+ this._formatNum(context.hour, patlen, false, out);
+ }
+ else if (c=='h')
+ {
+ var hour = context.hour;
+ if (hour == 0)
{
- var sum = 0;
+ hour = 12;
+ }
+ else if (hour > 12)
+ {
+ hour = hour - 12;
+ }
+ this._formatNum(hour, patlen, false, out);
+ }
+ else if (c=='m')
+ {
+ this._formatNum(context.min, patlen, false, out);
+ }
+ else if (c=='s')
+ {
+ this._formatNum(context.sec, patlen, false, out);
+ }
+ else if (c=='a')
+ {
+ out.append(symbols.ampms[context.ampm]);
+ }
+ else if (c=='w')
+ {
+ this._formatNum(context.weekOfWeekYear, patlen, false, out);
+ }
+ else
+ {
+ context.invalid = true;
+ }
+}
- for(var i=0;i<value.length;i++)
- {
- var c = value.charAt(i);
+proto._formatNum = function(num, length, ensureLength, out)
+{
+ var str = "" + num;
- if(c<'0'||c>'9')
- {
- return -1;
- }
- sum = sum*10+(c-'0');
- }
+ while(str.length<length)
+ {
+ str = "0" + str;
+ }
+
+ if (ensureLength && str.length > length)
+ {
+ str = str.substr(str.length - length);
+ }
- return sum;
- };
-org_apache_myfaces_SimpleDateFormat.prototype._fullYearFromDate = function(year)
- {
+ out.append(str);
+}
- var yearStr = year+"";
+proto._appendToArray = function(array, obj)
+{
+ array[array.length] = obj;
+}
- if (yearStr.length < 4)
- {
- return year+1900;
- }
+proto._isLetter = function(c)
+{
+ if ((c>= 'a') && (c<='z')) return true;
+ if ((c>='A') && (c<='Z')) return true;
+ return false;
+}
- return year;
- };
+proto._analysePattern = function(pattern)
+{
+ var patternIndex = 0;
+ var patternLen = pattern.length;
+ var lastChar = 0;
+ var patternSub = null;
+ var quoteMode = false;
+
+ var ops = new Array();
+
+ while (patternIndex < patternLen)
+ {
+ var currentChar = pattern.charAt(patternIndex);
+ var nextChar;
+
+ if (patternIndex < patternLen - 1)
+ {
+ nextChar = pattern.charAt(patternIndex + 1);
+ }
+ else
+ {
+ nextChar = 0;
+ }
-org_apache_myfaces_SimpleDateFormat.prototype._adjustTwoDigitYear = function(context)
- {
+ if (currentChar == '\'' && lastChar != '\\')
+ {
+ if (patternSub != null)
+ {
+ this._appendToArray(ops, patternSub.toString());
+ patternSub = null;
+ }
+ quoteMode = !quoteMode;
+ }
+ else if (quoteMode)
+ {
+ if (patternSub == null)
+ {
+ patternSub = new org_apache_myfaces_dateformat_StringBuffer("q:");
+ }
+ patternSub.append(currentChar);
+ }
+ else
+ {
+ if (currentChar == '\\' && lastChar != '\\')
+ {
+ // do nothing
+ }
+ else
+ {
+ if (patternSub == null)
+ {
+ if (this._isLetter(currentChar))
+ {
+ patternSub = new org_apache_myfaces_dateformat_StringBuffer("f:");
+ }
+ else
+ {
+ patternSub = new org_apache_myfaces_dateformat_StringBuffer("l:");
+ }
+ }
- if(context.ambigousYear)
- {
- var date = this._createDateFromContext(context);
- var threshold = this.dateFormatSymbols.twoDigitYearStart;
+ patternSub.append(currentChar);
+ if (currentChar != nextChar)
+ {
+ this._appendToArray(ops, patternSub.toString());
+ patternSub = null;
+ }
+ }
+ }
- if(date.getTime()<threshold.getTime())
- context.year += 100;
- }
- };
+ patternIndex++;
+ lastChar = currentChar;
+ }
+
+ if (patternSub != null)
+ {
+ this._appendToArray(ops, patternSub.toString());
+ }
-org_apache_myfaces_SimpleDateFormat.prototype._append = function(array, obj)
- {
- array[array.length] = obj;
- };
+ return ops;
+}
-//----------------------------------------------------------------------------
-// Make static method callable via short name
-//----------------------------------------------------------------------------
-org_apache_myfaces_SimpleDateFormat.prototype._weekNbr=org_apache_myfaces_SimpleDateFormat_weekNbr;
+proto._hasWeekPattern = function(ops)
+{
+ var wwPresent = false;
+ var xxPresent = false;
+ for(var i=0; i<ops.length; ++i)
+ {
+ var s = ops[i];
+ wwPresent = wwPresent || (s.indexOf("f:ww")==0);
+ xxPresent = xxPresent || (s.indexOf("f:xx")==0);
+ }
+
+ return wwPresent && !xxPresent;
+}
+
+// Constructor for SimpleDateFormatter class
+proto._construct = function(pattern, symbols, firstDayOfWeek)
+{
+ if (symbols == null)
+ {
+ this.symbols = new org_apache_myfaces_dateformat_DateFormatSymbols();
+ }
+ else
+ {
+ this.symbols = symbols;
+ }
+
+ this.ops = this._analysePattern(pattern);
+ this.yearIsWeekYear = this._hasWeekPattern(this.ops);
+
+ if (firstDayOfWeek != null)
+ this.firstDayOfWeek = firstDayOfWeek;
+ else
+ this.firstDayOfWeek = 1;
+}
+
+proto.setFirstDayOfWeek = function(dow)
+{
+ this.firstDayOfWeek = dow;
+}
+
+proto.parse = function(dateStr)
+{
+ if ((dateStr == null) || (dateStr.length == 0))
+ return null;
+
+ var context = this._parseOps(
+ this.symbols, this.yearIsWeekYear, this.firstDayOfWeek, this.ops,
+ dateStr);
+
+ if (context.invalid)
+ {
+ return null;
+ }
+
+ this._parsePostProcess(this.symbols, context);
+ return this._createDateFromContext(context);
+}
+
+proto.format = function(date)
+{
+ return this._formatOps(
+ this.symbols, this.yearIsWeekYear, this.firstDayOfWeek, this.ops,
+ date);
+}
+
+proto.getWeekDate = function(date)
+{
+ return this._getJavaWeekDate(date, this.firstDayOfWeek);
+}
+} // end of static init block for SimpleDateFormatter class
\ No newline at end of file