001: package net.sf.saxon.exslt;
002:
003: import java.text.SimpleDateFormat;
004: import java.util.Calendar;
005: import java.util.GregorianCalendar;
006:
007: /**
008: * This class implements extension functions in the
009: * http://exslt.org/dates-and-times namespace. <p>
010: */
011:
012: public final class Date {
013:
014: /**
015: * Private constructor to disallow instantiation
016: */
017:
018: private Date() {
019: };
020:
021: /**
022: * The date:date-time function returns the current date and time as a date/time string.
023: * The date/time string that's returned must be a string in the format defined as the
024: * lexical representation of xs:dateTime in [3.2.7 dateTime] of [XML Schema Part 2: Datatypes].
025: * The date/time format is basically CCYY-MM-DDThh:mm:ss+hh:mm.
026: * The date/time string format must include a time zone, either a Z to indicate
027: * Coordinated Universal Time or a + or - followed by the difference between the
028: * difference from UTC represented as hh:mm.
029: */
030:
031: public static String dateTime() {
032: Calendar calendar = new GregorianCalendar();
033: int tzoffset = calendar.get(Calendar.ZONE_OFFSET)
034: + calendar.get(Calendar.DST_OFFSET);
035: char sign = '+';
036: if (tzoffset < 0) {
037: sign = '-';
038: tzoffset = -tzoffset;
039: }
040: int tzminutes = tzoffset / 60000;
041: int tzhours = tzminutes / 60;
042: tzminutes = tzminutes % 60;
043: String tzh = "" + tzhours;
044: while (tzh.length() < 2)
045: tzh = "0" + tzh;
046: String tzm = "" + tzminutes;
047: while (tzm.length() < 2)
048: tzm = "0" + tzm;
049:
050: SimpleDateFormat formatter = new SimpleDateFormat(
051: "yyyy-MM-dd'T'HH:mm:ss");
052: String base = formatter.format(new java.util.Date());
053: return base + sign + tzh + ':' + tzm;
054: }
055:
056: /**
057: * The date:date function returns the date specified in the date/time string given as the
058: * argument.
059: * @param dateTime must start with [+|-]CCYY-MM-DD
060: */
061:
062: public static String date(String dateTime) {
063: int offset = 0;
064: if (dateTime.length() >= 1
065: && (dateTime.charAt(0) == '-' || dateTime.charAt(0) == '+')) {
066: offset = 1;
067: }
068: if (dateTime.length() >= offset + 10) {
069: return dateTime.substring(0, offset + 10);
070: } else {
071: return "";
072: }
073: }
074:
075: /**
076: * The date:date function returns the current date.
077: */
078:
079: public static String date() {
080: return date(dateTime());
081: }
082:
083: /**
084: * The date:time function returns the time specified in the date/time string given as the
085: * argument.
086: * @param dateTime must start with [+|-]CCYY-MM-DDThh:mm:ss
087: */
088:
089: public static String time(String dateTime) {
090: int t = dateTime.indexOf('T');
091: if (t < 0 || t == dateTime.length() - 1) {
092: return "";
093: } else {
094: return dateTime.substring(t + 1);
095: }
096: }
097:
098: /**
099: * The date:time function returns the current time.
100: */
101:
102: public static String time() {
103: return time(dateTime());
104: }
105:
106: /**
107: * The date:year function returns the year specified in the date/time string given as the
108: * argument.
109: * @param dateTime must begin with CCYY
110: */
111:
112: public static double year(String dateTime) {
113: if (dateTime.startsWith("-")) {
114: return Double.NaN;
115: }
116: try {
117: return (double) Integer.parseInt(dateTime.substring(0, 4));
118: } catch (Exception err) {
119: return Double.NaN;
120: }
121: }
122:
123: /**
124: * The date:year function returns the current year.
125: */
126:
127: public static double year() {
128: return year(dateTime());
129: }
130:
131: /**
132: * Return true if the year specified in the date/time string
133: * given as the argument is a leap year.
134: */
135:
136: public static boolean leapYear(String dateTime) {
137: double year = year(dateTime);
138: if (Double.isNaN(year)) {
139: return false;
140: }
141: int y = (int) year;
142: return (y % 4 == 0) && !((y % 100 == 0) && !(y % 400 == 0));
143: }
144:
145: /**
146: * Returns true if the current year is a leap year
147: */
148:
149: public static boolean leapYear() {
150: return leapYear(dateTime());
151: }
152:
153: /**
154: * Return the month number from a date.
155: * The date must start with either "CCYY-MM" or "--MM"
156: */
157:
158: public static double monthInYear(String dateTime) {
159: try {
160: if (dateTime.startsWith("--")) {
161: return (double) Integer.parseInt(dateTime.substring(2,
162: 4));
163: } else {
164: if (dateTime.indexOf('-') != 4) {
165: return Double.NaN;
166: }
167: return (double) Integer.parseInt(dateTime.substring(5,
168: 7));
169: }
170: } catch (Exception err) {
171: return Double.NaN;
172: }
173: }
174:
175: /**
176: * Return the month number from the current date.
177: */
178:
179: public static double monthInYear() {
180: return monthInYear(date());
181: }
182:
183: /**
184: * Return the month name from a date.
185: * The date must start with either "CCYY-MM" or "--MM"
186: * @return the English month name, for example "January", "February"
187: */
188:
189: public static String monthName(String date) {
190: String[] months = { "January", "February", "March", "April",
191: "May", "June", "July", "August", "September",
192: "October", "November", "December" };
193: double m = monthInYear(date);
194: if (Double.isNaN(m)) {
195: return "";
196: }
197: return months[(int) m - 1];
198: }
199:
200: /**
201: * Return the month name from the current date.
202: * @return the English month name, for example "January", "February"
203: */
204:
205: public static String monthName() {
206: return monthName(date());
207: }
208:
209: /**
210: * Return the month abbreviation from a date.
211: * The date must start with either "CCYY-MM" or "--MM"
212: * @return the English month abbreviation, for example "Jan", "Feb"
213: */
214:
215: public static String monthAbbreviation(String date) {
216: String[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
217: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
218: double m = monthInYear(date);
219: if (Double.isNaN(m)) {
220: return "";
221: }
222: return months[(int) m - 1];
223: }
224:
225: /**
226: * Return the month abbreviation from the current date.
227: * @return the English month abbreviation, for example "Jan", "Feb"
228: */
229:
230: public static String monthAbbreviation() {
231: return monthAbbreviation(date());
232: }
233:
234: /**
235: * Return the ISO week number of a specified date within the year
236: * (Note, this returns the ISO week number: the result in EXSLT is underspecified)
237: */
238:
239: public static double weekInYear(String dateTime) {
240: int dayInYear = (int) dayInYear(dateTime);
241: String firstJan = dateTime.substring(0, 4) + "-01-01";
242: int jan1day = ((int) dayInWeek(firstJan) + 5) % 7;
243: int daysInFirstWeek = (jan1day == 0 ? 0 : 7 - jan1day);
244:
245: int rawWeek = (dayInYear - daysInFirstWeek + 6) / 7;
246:
247: if (daysInFirstWeek >= 4) {
248: return rawWeek + 1;
249: } else {
250: if (rawWeek > 0) {
251: return rawWeek;
252: } else {
253: // week number should be 52 or 53: same as 31 Dec in previous year
254: int lastYear = Integer.parseInt(dateTime
255: .substring(0, 4)) - 1;
256: String dec31 = lastYear + "-12-31";
257: // assumes year > 999
258: return weekInYear(dec31);
259: }
260: }
261: }
262:
263: /**
264: * Return the ISO week number of the current date within the year
265: * (Note, this returns the ISO week number: the result in EXSLT is underspecified)
266: */
267:
268: public static double weekInYear() {
269: return weekInYear(date());
270: }
271:
272: /**
273: * Return the week number of a specified date within the month
274: * (Note, this function is underspecified in EXSLT)
275: */
276:
277: public static double weekInMonth(String dateTime) {
278: return (double) (int) ((dayInMonth(dateTime) - 1) / 7 + 1);
279: }
280:
281: /**
282: * Return the ISO week number of the current date within the month
283: */
284:
285: public static double weekInMonth() {
286: return weekInMonth(date());
287: }
288:
289: /**
290: * Return the day number of a specified date within the year
291: */
292:
293: public static double dayInYear(String dateTime) {
294: int month = (int) monthInYear(dateTime);
295: int day = (int) dayInMonth(dateTime);
296: int[] prev = {
297: 0,
298: 31,
299: 31 + 28,
300: 31 + 28 + 31,
301: 31 + 28 + 31 + 30,
302: 31 + 28 + 31 + 30 + 31,
303: 31 + 28 + 31 + 30 + 31 + 30,
304: 31 + 28 + 31 + 30 + 31 + 30 + 31,
305: 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
306: 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
307: 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
308: 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
309: 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
310: + 31 };
311: int leap = (month > 2 && leapYear(dateTime) ? 1 : 0);
312: return prev[month - 1] + leap + day;
313: }
314:
315: /**
316: * Return the day number of the current date within the year
317: */
318:
319: public static double dayInYear() {
320: return dayInYear(date());
321: }
322:
323: /**
324: * Return the day number of a specified date within the month
325: * @param dateTime must start with CCYY-MM-DD, or --MM-DD, or ---DD
326: */
327:
328: public static double dayInMonth(String dateTime) {
329: try {
330: if (dateTime.startsWith("---")) {
331: return (double) Integer.parseInt(dateTime.substring(3,
332: 5));
333: } else if (dateTime.startsWith("--")) {
334: return (double) Integer.parseInt(dateTime.substring(5,
335: 7));
336: } else {
337: return (double) Integer.parseInt(dateTime.substring(8,
338: 10));
339: }
340: } catch (Exception err) {
341: return Double.NaN;
342: }
343: }
344:
345: /**
346: * Return the day number of the current date within the month
347: */
348:
349: public static double dayInMonth() {
350: return dayInMonth(date());
351: }
352:
353: /**
354: * Return the day-of-the-week in a month of a date as a number
355: * (for example 3 for the 3rd Tuesday in May).
356: * @param dateTime must start with CCYY-MM-DD
357: */
358:
359: public static double dayOfWeekInMonth(String dateTime) {
360: double dd = dayInMonth(dateTime);
361: if (Double.isNaN(dd)) {
362: return dd;
363: }
364: return (((int) dd) - 1) / 7 + 1;
365: }
366:
367: /**
368: * Return the day-of-the-week in a month of the current date as a number
369: * (for example 3 for the 3rd Tuesday in May).
370: */
371:
372: public static double dayOfWeekInMonth() {
373: return dayOfWeekInMonth(date());
374: }
375:
376: /**
377: * Return the day of the week given in a date as a number.
378: * The numbering of days of the week starts at 1 for Sunday, 2 for Monday
379: * and so on up to 7 for Saturday.
380: * @param dateTime must start with CCYY-MM-DD
381: */
382:
383: public static double dayInWeek(String dateTime) {
384: double yy = year(dateTime);
385: double mm = monthInYear(dateTime);
386: double dd = dayInMonth(dateTime);
387: if (Double.isNaN(yy) || Double.isNaN(mm) || Double.isNaN(dd)) {
388: return Double.NaN;
389: }
390: GregorianCalendar calDate = new GregorianCalendar((int) yy,
391: (int) mm - 1, (int) dd);
392: calDate.setFirstDayOfWeek(Calendar.SUNDAY);
393: return calDate.get(Calendar.DAY_OF_WEEK);
394: }
395:
396: /**
397: * Return the day of the week in the current date as a number.
398: * The numbering of days of the week starts at 1 for Sunday, 2 for Monday
399: * and so on up to 7 for Saturday.
400: */
401:
402: public static double dayInWeek() {
403: return dayInWeek(date());
404: }
405:
406: /**
407: * Return the day of the week given in a date as an English day name:
408: * one of 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday' or 'Friday'.
409: * @param dateTime must start with CCYY-MM-DD
410: */
411:
412: public static String dayName(String dateTime) {
413: String[] days = { "Sunday", "Monday", "Tuesday", "Wednesday",
414: "Thursday", "Friday", "Saturday" };
415: double d = dayInWeek(dateTime);
416: if (Double.isNaN(d)) {
417: return "";
418: }
419: return days[(int) d - 1];
420: }
421:
422: /**
423: * Return the day of the week given in the current date as an English day name:
424: * one of 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday' or 'Friday'.
425: */
426:
427: public static String dayName() {
428: return dayName(date());
429: }
430:
431: /**
432: * Return the day of the week given in a date as an English day abbreviation:
433: * one of 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', or 'Sat'.
434: * @param dateTime must start with CCYY-MM-DD
435: */
436:
437: public static String dayAbbreviation(String dateTime) {
438: String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
439: "Sat" };
440: double d = dayInWeek(dateTime);
441: if (Double.isNaN(d)) {
442: return "";
443: }
444: return days[(int) d - 1];
445: }
446:
447: /**
448: * Return the day of the week given in the current date as an English day abbreviation:
449: * one of 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', or 'Sat'.
450: */
451:
452: public static String dayAbbreviation() {
453: return dayAbbreviation(date());
454: }
455:
456: /**
457: * Return the hour of the day in the specified date or date/time
458: * @param dateTime must start with CCYY-MM-DDThh:mm:ss or hh:mm:ss
459: */
460:
461: public static double hourInDay(String dateTime) {
462: int t = dateTime.indexOf('T');
463: try {
464: int hh = Integer.parseInt(dateTime.substring(t + 1, t + 3));
465: return (double) hh;
466: } catch (Exception err) {
467: return Double.NaN;
468: }
469: }
470:
471: /**
472: * Return the current hour of the day
473: */
474:
475: public static double hourInDay() {
476: return hourInDay(time());
477: }
478:
479: /**
480: * Return the minute of the hour in the specified date or date/time
481: * @param dateTime must start with CCYY-MM-DDThh:mm:ss or hh:mm:ss
482: */
483:
484: public static double minuteInHour(String dateTime) {
485: int t = dateTime.indexOf('T');
486: try {
487: int mm = Integer.parseInt(dateTime.substring(t + 4, t + 6));
488: return (double) mm;
489: } catch (Exception err) {
490: return Double.NaN;
491: }
492: }
493:
494: /**
495: * Return the current minute of the hour
496: */
497:
498: public static double minuteInHour() {
499: return minuteInHour(time());
500: }
501:
502: /**
503: * Return the second of the minute in the specified date or date/time
504: * @param dateTime must start with CCYY-MM-DDThh:mm:ss or hh:mm:ss
505: */
506:
507: public static double secondInMinute(String dateTime) {
508: int t = dateTime.indexOf('T');
509: try {
510: int ss = Integer.parseInt(dateTime.substring(t + 7, t + 9));
511: return (double) ss;
512: } catch (Exception err) {
513: return Double.NaN;
514: }
515: }
516:
517: /**
518: * Return the current second of the minute
519: */
520:
521: public static double secondInMinute() {
522: return secondInMinute(time());
523: }
524:
525: }
526:
527: //
528: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
529: // you may not use this file except in compliance with the License. You may obtain a copy of the
530: // License at http://www.mozilla.org/MPL/
531: //
532: // Software distributed under the License is distributed on an "AS IS" basis,
533: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
534: // See the License for the specific language governing rights and limitations under the License.
535: //
536: // The Original Code is: all this file.
537: //
538: // The Initial Developer of the Original Code is Michael H. Kay.
539: //
540: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
541: //
542: // Contributor(s): none.
543: //
|