/*
* $Id: AnyCalendar.java,v 1.28 2002/09/16 08:05:03 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.core.time;
import anvil.core.Any;
import anvil.core.AnyAbstractClass;
import anvil.core.AnyString;
import anvil.core.Serialization;
import anvil.core.Serializer;
import anvil.core.Unserializer;
import anvil.core.UnserializationException;
import anvil.script.Context;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.io.OutputStream;
import java.io.IOException;
import java.io.Writer;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.TimeZone;
/// @class Calendar
/// Calendar represents any time with millisecond precision.
/**
* class AnyCalendar
*
* @author: Jani Lehtim�ki
*/
public class AnyCalendar extends AnyAbstractClass
{
/// @constructor Calendar
/// Creates instance of Calendar
/// @synopsis Calendar(int timestamp [, string timezone])
/// @synopsis Calendar(int year, int month [, string timezone])
/// @synopsis Calendar(int year, int month, int day [, string timezone])
/// @synopsis Calendar(int year, int month, int day, int hour [, string timezone])
/// @synopsis Calendar(int year, int month, int day, int hour, int minute [, string timezone])
/// @synopsis Calendar(int year, int month, int day, int hour, int minute, int second [, string timezone])
/// @synopsis Calendar(int tear, int month, int day, int hour, int minute, int second, int millisecond [, string timezone])
/// @param timezone ID of timezone, as string
public static final Object[] newInstance = { new Integer(0), null, "parameters"};
public static final Any newInstance(Context context, Any[] parameters)
{
int length = parameters.length;
if (length == 0) {
return TimeModule.getTime(context, null, null);
}
String timezone;
if (parameters[length-1].isString()) {
timezone = parameters[--length].toString();
} else {
timezone = TimeZone.getDefault().getID();
}
int hour = 0;
int minute = 0;
int second = 0;
int millis = 0;
int day = 1;
int month = 1;
switch(length) {
default:
case 7:
millis = parameters[--length].toInt();
case 6:
second = parameters[--length].toInt();
case 5:
minute = parameters[--length].toInt();
case 4:
hour = parameters[--length].toInt();
case 3:
day = parameters[--length].toInt();
case 2:
month = parameters[--length].toInt();
int year = parameters[--length].toInt();
return AnyCalendar.create(year, month, day, hour, minute, second, millis, timezone);
case 1:
long timestamp = parameters[--length].toLong();
return AnyCalendar.create(timestamp, timezone);
case 0:
throw context.NotEnoughParameters();
}
}
private static Hashtable _fieldLookup = new Hashtable();
private static final int INVALID = -999999;
static {
_fieldLookup.put("year", new Integer(Calendar.YEAR));
_fieldLookup.put("month", new Integer(Calendar.MONTH));
_fieldLookup.put("day", new Integer(Calendar.DAY_OF_MONTH));
_fieldLookup.put("week", new Integer(Calendar.WEEK_OF_YEAR));
_fieldLookup.put("weekOfYear", new Integer(Calendar.WEEK_OF_YEAR));
_fieldLookup.put("weekOfMonth", new Integer(Calendar.WEEK_OF_MONTH));
_fieldLookup.put("dayOfYear", new Integer(Calendar.DAY_OF_YEAR));
_fieldLookup.put("dayOfMonth", new Integer(Calendar.DAY_OF_MONTH));
_fieldLookup.put("dayOfWeek", new Integer(Calendar.DAY_OF_WEEK));
_fieldLookup.put("dayOfWeekInMonth", new Integer(Calendar.DAY_OF_WEEK_IN_MONTH));
_fieldLookup.put("hour", new Integer(Calendar.HOUR_OF_DAY));
_fieldLookup.put("minute", new Integer(Calendar.MINUTE));
_fieldLookup.put("second", new Integer(Calendar.SECOND));
_fieldLookup.put("millisecond", new Integer(Calendar.MILLISECOND));
_fieldLookup.put("zoneOffset", new Integer(Calendar.ZONE_OFFSET));
}
private static int getFieldId(Any value)
{
if (value.isInt()) {
return value.toInt();
}
Integer field = (Integer)_fieldLookup.get(value.toString());
if (field != null) {
return field.intValue();
} else {
return INVALID;
}
}
private static int getFieldId(String name)
{
Integer field = (Integer)_fieldLookup.get(name);
if (field != null) {
return field.intValue();
} else {
return INVALID;
}
}
public static Any create(int year, int month, int day,
int hour, int minute, int second, int millis, String zone)
{
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zone));
cal.set(year, month, day, hour, minute, second);
cal.set(Calendar.MILLISECOND, millis);
return new AnyCalendar(cal);
}
public static Any create(long timestamp, String zone)
{
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(zone));
cal.setTime(new Date(timestamp));
return new AnyCalendar(cal);
}
private Calendar _calendar;
public AnyCalendar(Calendar calendar)
{
_calendar = calendar;
}
public final anvil.script.ClassType classOf()
{
return __class__;
}
public Object clone()
{
return new AnyCalendar((Calendar)_calendar.clone());
}
public Any copy()
{
return new AnyCalendar((Calendar)_calendar.clone());
}
public int hashCode()
{
return _calendar.hashCode();
}
public boolean equals(Object o)
{
if (o instanceof AnyCalendar) {
return _calendar.equals(((AnyCalendar)o)._calendar);
}
return false;
}
public String toString()
{
return anvil.util.Conversions.toString(_calendar);
}
public Writer toAnvil(Writer writer) throws IOException
{
Calendar calendar = _calendar;
writer.write("new anvil.time.Calendar(");
writer.write(Integer.toString(calendar.get(calendar.YEAR)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MONTH) + 1));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.DAY_OF_MONTH)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.HOUR_OF_DAY)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MINUTE)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.SECOND)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MILLISECOND)));
writer.write(", \"");
writer.write(anvil.util.Conversions.escape(calendar.getTimeZone().getID(), true));
writer.write("\")");
return writer;
}
public Writer toJava(Writer writer) throws IOException
{
Calendar calendar = _calendar;
writer.write("anvil.core.time.AnyCalendar.create(");
writer.write(Integer.toString(calendar.get(calendar.YEAR)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MONTH) + 1));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.DAY_OF_MONTH)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.HOUR_OF_DAY)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MINUTE)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.SECOND)));
writer.write(", ");
writer.write(Integer.toString(calendar.get(calendar.MILLISECOND)));
writer.write(", \"");
writer.write(anvil.util.Conversions.escape(calendar.getTimeZone().getID(), true));
writer.write("\")");
return writer;
}
public anvil.codec.Code toCode(anvil.codec.Code code)
{
Calendar calendar = _calendar;
anvil.codec.ConstantPool pool = code.getPool();
code.iconst(calendar.get(calendar.YEAR));
code.iconst(calendar.get(calendar.MONTH) + 1);
code.iconst(calendar.get(calendar.DAY_OF_MONTH));
code.iconst(calendar.get(calendar.HOUR_OF_DAY));
code.iconst(calendar.get(calendar.MINUTE));
code.iconst(calendar.get(calendar.SECOND));
code.iconst(calendar.get(calendar.MILLISECOND));
code.astring(calendar.getTimeZone().getID());
code.invokestatic(code.getPool().addMethodRef("anvil/core/time/AnyCalendar",
"create", "(IIIIIIILjava/lang/String;)Lanvil/core/Any;"));
return code;
}
public Object toObject()
{
return _calendar;
}
public Any getAttribute(Context context, String attribute)
{
int field = getFieldId(attribute);
if (field != INVALID) {
return Any.create(_calendar.get(field));
} else {
throw context.AttributeError("anvil.time.Calendar." + attribute);
}
}
public Any setAttribute(Context context, String attribute, Any value)
{
int field = getFieldId(attribute);
if (field != INVALID) {
_calendar.set(field, value.toInt());
} else {
throw context.AttributeError("anvil.time.Calendar." + attribute);
}
return this;
}
public Any checkAttribute(Context context, String attribute)
{
int field = getFieldId(attribute);
if (field != INVALID) {
return Any.create(_calendar.get(field));
} else {
return UNDEFINED;
}
}
public boolean deleteAttribute(Context context, String attribute)
{
throw context.AttributeError("anvil.time.Calendar." + attribute);
}
public Any getReference(Context context, Any index)
{
int field = getFieldId(index);
if (field != INVALID) {
return Any.create(_calendar.get(field));
} else {
throw context.ReferenceError("anvil.time.Calendar[" + index + ']');
}
}
public Any setReference(Context context, Any index, Any value)
{
int field = getFieldId(index);
if (field != INVALID) {
_calendar.set(field, value.toInt());
} else {
throw context.ReferenceError("anvil.time.Calendar[" + index + ']');
}
return this;
}
public Any checkReference(Context context, Any index)
{
int field = getFieldId(index);
if (field != INVALID) {
return Any.create(_calendar.get(field));
} else {
return UNDEFINED;
}
}
public boolean deleteReference(Context context, Any index)
{
throw context.ReferenceError("anvil.time.Calendar[" + index + ']');
}
public void serialize(Serializer serializer) throws IOException
{
if (serializer.register(this)) {
return;
}
serializer.write('C');
serializer.write(_calendar.get(Calendar.YEAR));
serializer.write(':');
serializer.write(_calendar.get(Calendar.MONTH));
serializer.write(':');
serializer.write(_calendar.get(Calendar.DAY_OF_MONTH));
serializer.write(':');
serializer.write(_calendar.get(Calendar.HOUR_OF_DAY));
serializer.write(':');
serializer.write(_calendar.get(Calendar.MINUTE));
serializer.write(':');
serializer.write(_calendar.get(Calendar.SECOND));
serializer.write(':');
serializer.write(_calendar.get(Calendar.MILLISECOND));
serializer.write(':');
serializer.write(_calendar.getTimeZone().getID());
}
public static final Any unserialize(Unserializer unserializer)
throws UnserializationException
{
int year = (int)unserializer.getLong();
int month = (int)unserializer.getLong();
int day = (int)unserializer.getLong();
int hour = (int)unserializer.getLong();
int minute = (int)unserializer.getLong();
int second = (int)unserializer.getLong();
int millis = (int)unserializer.getLong();
unserializer.consume('s');
String zone = unserializer.getUTF16String();
Any cal = create(year, month, day, hour, minute, second, millis, zone);
unserializer.register(cal);
return cal;
}
/// @method after
/// Checks if current time is after the given time.
/// @synopsis Calendar after(Calendar other)
public static final Object[] p_after = { null, "other" };
public Any m_after(Context context, Any other)
{
if (other instanceof AnyCalendar) {
Calendar parameter = ((AnyCalendar)other)._calendar;
return _calendar.after(parameter) ? TRUE : FALSE;
} else {
throw context.BadParameter("Calendar expected");
}
}
/// @method before
/// Checks if current time is before the given time.
/// @synopsis Calendar before(Calendar other)
public static final Object[] p_before = { null, "other" };
public Any m_before(Context context, Any other)
{
if (other instanceof AnyCalendar) {
Calendar parameter = ((AnyCalendar)other)._calendar;
return _calendar.before(parameter) ? TRUE : FALSE;
} else {
throw context.BadParameter("Calendar expected");
}
}
/// @method roll
/// Rolls specified field up or down a single unit, or given amount.
/// When rolling another fields are not affected unless they resulting
/// time would be non-existents (such as February 31).
/// @synopsis Calendar roll(int field, int amount)
/// @synopsis Calendar roll(string field, int amount)
/// @synopsis Calendar roll(int field, boolean up)
/// @synopsis Calendar roll(string field, boolean up)
/// @param up true for up, false for down
/// @param amount Amount of adjustment for given field, negative value rolls down.
public static final Object[] p_roll = { null, "field", "upOrAmount" };
public Any m_roll(Context context, Any field_, Any p)
{
int field = getFieldId(field_);
if (field != INVALID) {
if (p.isBoolean()) {
_calendar.roll(field, p.toBoolean());
} else {
_calendar.roll(field, p.toInt());
}
return this;
} else {
throw context.AttributeError("anvil.time.Calendar[" + field_ + ']');
}
}
/// @method add
/// Moves time forward or backward given amount of time units.
/// Unit depends on given field.
/// @synopsis Calendar add(int field, int amount)
/// @synopsis Calendar add(string field, int amount)
public static final Object[] p_add = { null, "field", "amout" };
public Any m_add(Context context, Any field_, int amount)
{
int field = getFieldId(field_);
if (field != INVALID) {
_calendar.add(field, amount);
return this;
} else {
throw context.AttributeError("anvil.time.Calendar[" + field_ + ']');
}
}
/// @method setFirstDayOfWeek
/// Sets the first day of week.
/// @synopsis Calendar setFirstDayOfWeek(int firstDayOfWeek)
public static final Object[] p_setFirstDayOfWeek = { "firstDay" };
public Any m_setFirstDayOfWeek(int firstDay)
{
_calendar.setFirstDayOfWeek(firstDay);
return this;
}
/// @method getFirstDayOfWeek
/// Gets the first day of week.
/// @synopsis int getFirstDayOfWeek()
public Any m_getFirstDayOfWeek()
{
return Any.create(_calendar.getFirstDayOfWeek());
}
/// @method getLastDayOfWeek
/// Gets the last day of week.
/// @synopsis int getLastDayOfWeek()
public Any m_getLastDayOfWeek()
{
int day = _calendar.getFirstDayOfWeek();
day += 6;
if (day > Calendar.SATURDAY) {
day -= Calendar.SATURDAY;
}
return Any.create(day);
}
/// @method getTime
/// Returns the timestamp for this time.
/// Timestamp is milliseconds since 1.1.1970 00:00.
/// @synopsis int getTime()
public Any m_getTime()
{
return Any.create(_calendar.getTime().getTime());
}
/// @method setTime
/// Sets this time by using timestamp.
/// Timestamp is milliseconds since 1.1.1970 00:00.
/// @synopsis Calendar setTime(int timestamp)
public static final Object[] p_setTime = { "timestamp" };
public Any m_setTime(long timestamp)
{
_calendar.setTime(new Date(timestamp));
return this;
}
/// @method set
/// Sets the time.
/// @synopsis Calendar set(int fieldId, int setting)
/// @synopsis Calendar set(string fieldId, int setting)
/// @synopsis Calendar set(int year, int month, int day)
/// @synopsis Calendar set(int year, int month, int day)
/// @synopsis Calendar set(int year, int month, int day, int hour, int minute)
/// @synopsis Calendar set(int year, int month, int day, int hour, int minute, int second)
public static final Object[] p_set = { null, "parameters" };
public Any m_set(Context context, Any[] parameters)
{
int n = parameters.length;
Calendar calendar = _calendar;
switch(n) {
case 2: {
int field = getFieldId(parameters[0]);
if (field != INVALID) {
calendar.set(field, parameters[1].toInt());
return this;
} else {
throw context.AttributeError("anvil.time.Calendar[" + parameters[0] + ']');
}
}
case 3: {
int year = parameters[0].toInt();
int month = parameters[1].toInt();
int day = parameters[2].toInt();
calendar.set(year, month, day);
}
break;
case 5: {
int year = parameters[0].toInt();
int month = parameters[1].toInt();
int day = parameters[2].toInt();
int hour = parameters[3].toInt();
int minute = parameters[4].toInt();
calendar.set(year, month, day, hour, minute);
}
break;
case 6: {
int year = parameters[0].toInt();
int month = parameters[1].toInt();
int day = parameters[2].toInt();
int hour = parameters[3].toInt();
int minute = parameters[4].toInt();
int second = parameters[5].toInt();
calendar.set(year, month, day, hour, minute, second);
}
break;
default:
throw context.BadParameter("Invalid number of parameters");
}
return this;
}
public void pad(StringBuffer buffer, int i)
{
buffer.append((char)('0' + (i / 10)));
buffer.append((char)('0' + (i % 10)));
}
/// @method pack
/// Packs the time into compact string representation.
/// @synopsis string pack()
/// @synopsis string pack(int level)
/// @param level Level of detail, between 1 and 6:
/// 1 for year, 2 for month, 3 for day of month,
/// 4 for hour, 5 minute, 6 seconds.
public static final Object[] p_pack = { "*level", null };
public Any m_pack(Any level_)
{
int level = 5;
if (level_ != null) {
level = level_.toInt();
}
if (level < 1) {
return EMPTY_STRING;
}
StringBuffer buffer = new StringBuffer(4 + 2 * (level - 1));
if (level >= 1) {
buffer.append(_calendar.get(Calendar.YEAR));
if (level >= 2) {
pad(buffer, _calendar.get(Calendar.MONTH));
if (level >= 3) {
pad(buffer, _calendar.get(Calendar.DAY_OF_MONTH));
if (level >= 4) {
pad(buffer, _calendar.get(Calendar.HOUR_OF_DAY));
if (level >= 5) {
pad(buffer, _calendar.get(Calendar.MINUTE));
if (level >= 6) {
pad(buffer, _calendar.get(Calendar.SECOND));
}
}
}
}
}
}
return new AnyString(buffer.toString());
}
/// @method unpack
/// Unpacks packed time and sets this calendar to reflect that time.
/// @synopsis Calendar unpack(string packedTime)
public static final Object[] p_unpack = { null, "packedTime" };
public Any m_unpack(Context context, String packed)
{
int n = packed.length();
int year = 0;
int month = 0;
int day = 1;
int hour = 0;
int minute = 0;
int second = 0;
try {
if (n>=4) {
year = Integer.parseInt(packed.substring(0, 4));
if (n>=6) {
month = Integer.parseInt(packed.substring(4, 6));
if (n>=8) {
day = Integer.parseInt(packed.substring(6, 8));
if (n>=10) {
hour = Integer.parseInt(packed.substring(8, 10));
if (n>=12) {
minute = Integer.parseInt(packed.substring(10, 12));
if (n>=14) {
second = Integer.parseInt(packed.substring(12, 14));
}
}
}
}
}
_calendar.set(year, month, day, hour, minute, second);
return this;
}
} catch (NumberFormatException e) {
throw context.BadParameter("Invalid number: "+e.getMessage());
}
return this;
}
/// @method onSameDay
/// Checks if given time is on same day as this.
/// @synopsis boolean onSameDay(Calendar other)
public static final Object[] p_onSameDay = { null, "packedTime" };
public Any m_onSameDay(Context context, Any other)
{
if (other instanceof AnyCalendar) {
Calendar a = _calendar;
Calendar b = ((AnyCalendar)other)._calendar;
return (a.get(Calendar.YEAR) == b.get(Calendar.YEAR)) &&
(a.get(Calendar.MONTH) == b.get(Calendar.MONTH)) &&
(a.get(Calendar.DAY_OF_MONTH) == b.get(Calendar.DAY_OF_MONTH)) ?
TRUE : FALSE;
} else {
throw context.BadParameter("Calendar expected");
}
}
/// @method format
/// See java.text.SimpleDateFormat.
/// @synopsis string format(string format)
public static final Object[] p_format = { null, "format" };
public Any m_format(Context context, String format)
{
try {
DateFormatSymbols dfsymbols = new DateFormatSymbols(context.getLocale());
SimpleDateFormat df = new SimpleDateFormat(format, dfsymbols);
return Any.create(df.format(_calendar.getTime()));
} catch (IllegalArgumentException e) {
throw context.BadParameter(e.getMessage());
}
}
public static final anvil.script.compiler.NativeClass __class__ =
new anvil.script.compiler.NativeClass("Calendar", AnyCalendar.class,
//DOC{{
""+
" @class Calendar\n" +
" Calendar represents any time with millisecond precision.\n" +
" @constructor Calendar\n" +
" Creates instance of Calendar\n" +
" @synopsis Calendar(int timestamp [, string timezone])\n" +
" @synopsis Calendar(int year, int month [, string timezone])\n" +
" @synopsis Calendar(int year, int month, int day [, string timezone])\n" +
" @synopsis Calendar(int year, int month, int day, int hour [, string timezone])\n" +
" @synopsis Calendar(int year, int month, int day, int hour, int minute [, string timezone])\n" +
" @synopsis Calendar(int year, int month, int day, int hour, int minute, int second [, string timezone])\n" +
" @synopsis Calendar(int tear, int month, int day, int hour, int minute, int second, int millisecond [, string timezone])\n" +
" @param timezone ID of timezone, as string\n" +
" @method after\n" +
" Checks if current time is after the given time.\n" +
" @synopsis Calendar after(Calendar other)\n" +
" @method before\n" +
" Checks if current time is before the given time.\n" +
" @synopsis Calendar before(Calendar other)\n" +
" @method roll\n" +
" Rolls specified field up or down a single unit, or given amount.\n" +
" When rolling another fields are not affected unless they resulting \n" +
" time would be non-existents (such as February 31).\n" +
" @synopsis Calendar roll(int field, int amount)\n" +
" @synopsis Calendar roll(string field, int amount)\n" +
" @synopsis Calendar roll(int field, boolean up)\n" +
" @synopsis Calendar roll(string field, boolean up)\n" +
" @param up true for up, false for down\n" +
" @param amount Amount of adjustment for given field, negative value rolls down.\n" +
" @method add\n" +
" Moves time forward or backward given amount of time units. \n" +
" Unit depends on given field.\n" +
" @synopsis Calendar add(int field, int amount)\n" +
" @synopsis Calendar add(string field, int amount)\n" +
" @method setFirstDayOfWeek\n" +
" Sets the first day of week.\n" +
" @synopsis Calendar setFirstDayOfWeek(int firstDayOfWeek)\n" +
" @method getFirstDayOfWeek\n" +
" Gets the first day of week. \n" +
" @synopsis int getFirstDayOfWeek()\n" +
" @method getLastDayOfWeek\n" +
" Gets the last day of week. \n" +
" @synopsis int getLastDayOfWeek()\n" +
" @method getTime\n" +
" Returns the timestamp for this time.\n" +
" Timestamp is milliseconds since 1.1.1970 00:00.\n" +
" @synopsis int getTime()\n" +
" @method setTime\n" +
" Sets this time by using timestamp.\n" +
" Timestamp is milliseconds since 1.1.1970 00:00.\n" +
" @synopsis Calendar setTime(int timestamp)\n" +
" @method set\n" +
" Sets the time.\n" +
" @synopsis Calendar set(int fieldId, int setting)\n" +
" @synopsis Calendar set(string fieldId, int setting)\n" +
" @synopsis Calendar set(int year, int month, int day)\n" +
" @synopsis Calendar set(int year, int month, int day)\n" +
" @synopsis Calendar set(int year, int month, int day, int hour, int minute)\n" +
" @synopsis Calendar set(int year, int month, int day, int hour, int minute, int second)\n" +
" @method pack\n" +
" Packs the time into compact string representation.\n" +
" @synopsis string pack()\n" +
" @synopsis string pack(int level)\n" +
" @param level Level of detail, between 1 and 6:\n" +
" 1 for year, 2 for month, 3 for day of month,\n" +
" 4 for hour, 5 minute, 6 seconds.\n" +
" @method unpack\n" +
" Unpacks packed time and sets this calendar to reflect that time.\n" +
" @synopsis Calendar unpack(string packedTime)\n" +
" @method onSameDay\n" +
" Checks if given time is on same day as this.\n" +
" @synopsis boolean onSameDay(Calendar other)\n" +
" @method format \n" +
" See java.text.SimpleDateFormat.\n" +
" @synopsis string format(string format)\n"
//}}DOC
);
static {
TimeModule.class.getName();
}
}