org.apache.myfaces.custom.calendar.resource.date.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tomahawk Show documentation
Show all versions of tomahawk Show documentation
JSF components and utilities that can be used with any JSF implementation.
This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there
is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to
offer some additional benefits.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
//----------------------------------------------------------------------------
// 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_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 optionally supports ISO-8601 weeks, and the JODA
// "xxxx" pattern for weekYear.
//
// 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.
//----------------------------------------------------------------------------
// Constructor for DateFormatSymbols class
org_apache_myfaces_dateformat_DateFormatSymbols = 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 threshold = new Date();
threshold.setYear(threshold.getYear()-80);
this.twoDigitYearStart = threshold;
}
// 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;
}
// constructor for WeekDate class
org_apache_myfaces_dateformat_WeekDate = function(year, week)
{
this.year = year;
this.week = week;
}
// constructor for StringBuffer class
org_apache_myfaces_dateformat_StringBuffer = function(s)
{
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;
}
}
// Constructor for SimpleDateFormatter class
org_apache_myfaces_dateformat_SimpleDateFormatter = function(pattern, symbols, firstDayOfWeek)
{
this._construct(pattern, symbols, firstDayOfWeek);
}
// 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.
{
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);
}
}
proto._isLeapYear = function(year)
{
return ((year%4 == 0) && (year%100 != 0)) || (year%400 == 0);
}
proto._dayOfWeek = function(year, month, day)
{
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;
}
proto._getWeekDate = 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))
{
return new org_apache_myfaces_dateformat_WeekDate(year-1, 53);
}
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);
}
}
proto._getStartOfWeekYear = function(year, firstDayOfWeek)
{
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;
}
proto._getDateForWeekDate = 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;
}
proto._fullYearFromDate = function(year)
{
if (year < 1900)
{
return year+1900;
}
else
{
return year;
}
}
proto._createDateFromContext = function(context)
{
var date;
if (context.weekOfWeekYear != 0)
{
date = this._getDateForWeekDate(
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;
}
proto._substr = function(s, start, len)
{
var s2 = s.substring(start);
if (s2.length <= len)
return s2;
else
return s2.substring(0, len);
}
proto._parseOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, dateStr)
{
var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
var dateIndex = 0;
var dateStrLen = dateStr.length;
for(var i=0; (i= 4)
{
var fragment = dateStr.substring(dateIndex);
var index = this._parsePrefixOf(context, symbols.months, fragment);
if (index != -1)
{
context.month = index;
}
}
else
{
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;
}
}
proto._parseInt = function(value)
{
var sum = 0;
for(var i=0;i'9')
{
return -1;
}
sum = sum*10+(c-'0');
}
return sum;
}
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;
}
proto._parsePrefixOf = function(context, array, value)
{
for (var i=0; i 0)
{
if (context.ampm == 1)
{
context.hour = context.hourAmpm + 12;
if (context.hour == 24)
context.hour = 0;
}
else
{
context.hour = context.hourAmpm;
}
}
}
proto._formatOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, date)
{
var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
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._getWeekDate(date, firstDayOfWeek);
context.weekYear = weekDate.year;
context.weekOfWeekYear = weekDate.week;
var str = new org_apache_myfaces_dateformat_StringBuffer();
for(var i=0; i= 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)
{
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;
}
}
proto._formatNum = function(num, length, ensureLength, out)
{
var str = "" + num;
while(str.length length)
{
str = str.substr(str.length - length);
}
out.append(str);
}
proto._appendToArray = function(array, obj)
{
array[array.length] = obj;
}
proto._isLetter = function(c)
{
if ((c>= 'a') && (c<='z')) return true;
if ((c>='A') && (c<='Z')) return true;
return false;
}
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;
}
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:");
}
}
patternSub.append(currentChar);
if (currentChar != nextChar)
{
this._appendToArray(ops, patternSub.toString());
patternSub = null;
}
}
}
patternIndex++;
lastChar = currentChar;
}
if (patternSub != null)
{
this._appendToArray(ops, patternSub.toString());
}
return ops;
}
proto._hasWeekPattern = function(ops)
{
var wwPresent = false;
var xxPresent = false;
for(var i=0; i