package php.runtime.ext.core.classes.time;
import php.runtime.Memory;
import php.runtime.common.HintType;
import php.runtime.env.Environment;
import php.runtime.ext.core.classes.util.WrapLocale;
import php.runtime.lang.BaseObject;
import php.runtime.lang.support.IComparableObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.LongMemory;
import php.runtime.memory.ObjectMemory;
import php.runtime.memory.StringMemory;
import php.runtime.reflection.ClassEntity;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import static php.runtime.annotation.Reflection.*;
import static php.runtime.annotation.Runtime.FastMethod;
@Name("php\\time\\Time")
public class WrapTime extends BaseObject implements IComparableObject<WrapTime> {
protected final static TimeZone UTC = TimeZone.getTimeZone("UTC");
protected Date date;
protected TimeZone timeZone;
protected Calendar calendar;
protected Locale locale;
public WrapTime(Environment env, Date date) {
super(env);
this.date = date;
timeZone = UTC;
calendar = Calendar.getInstance(UTC, Locale.ENGLISH);
calendar.setTime(date);
locale = Locale.ENGLISH;
}
public WrapTime(Environment env, Date date, TimeZone timeZone) {
this(env, date, timeZone, null);
}
public WrapTime(Environment env, Date date, TimeZone timeZone, Locale locale) {
super(env);
this.date = date;
this.timeZone = timeZone;
this.locale = locale == null ? Locale.ENGLISH : locale;
this.calendar = Calendar.getInstance(timeZone, this.locale);
calendar.setTime(date);
}
public WrapTime(Environment env, ClassEntity clazz) {
super(env, clazz);
}
public Date getDate() {
return date;
}
public TimeZone getTimeZone() {
return timeZone;
}
public Calendar getCalendar() {
return calendar;
}
@Signature({
@Arg(value = "date", optional = @Optional("null")),
@Arg(value = "timeZone", nativeType = WrapTimeZone.class, optional = @Optional("null")),
@Arg(value = "locale", nativeType = WrapLocale.class, optional = @Optional("null"))
})
public Memory __construct(Environment env, Memory... args) {
TimeZone zone = WrapTimeZone.getTimeZone(env, args[1]);
this.timeZone = zone;
this.locale = args[2].isNull() ? Locale.ENGLISH : args[2].toObject(WrapLocale.class).getLocale();
this.date = args[0].isNull() ? Calendar.getInstance(zone, this.locale).getTime() : new Date(args[0].toLong());
calendar = Calendar.getInstance(timeZone, this.locale);
calendar.setTime(date);
return Memory.NULL;
}
@Signature
public Memory __debugInfo(Environment env, Memory... args) {
ArrayMemory r = new ArrayMemory();
r.refOfIndex("*time").assign(date.getTime());
r.refOfIndex("*timeZone").assign(timeZone.getID());
return r.toConstant();
}
@Signature
public Memory getTime(Environment env, Memory... args) {
return LongMemory.valueOf(date.getTime());
}
@Signature
public Memory year(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.YEAR));
}
@Signature
public Memory month(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.MONTH) + 1);
}
@Signature
public Memory week(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.WEEK_OF_YEAR));
}
@Signature
public Memory weekOfMonth(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.WEEK_OF_MONTH));
}
@Signature
public Memory day(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.DAY_OF_YEAR));
}
@Signature
public Memory dayOfMonth(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
}
@Signature
public Memory dayOfWeek(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.DAY_OF_WEEK));
}
@Signature
public Memory dayOfWeekInMonth(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
}
@Signature
public Memory hour(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.HOUR));
}
@Signature
public Memory hourOfDay(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.HOUR_OF_DAY));
}
@Signature
public Memory minute(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.MINUTE));
}
@Signature
public Memory second(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.SECOND));
}
@Signature
public Memory millisecond(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.get(Calendar.MILLISECOND));
}
@Signature
public Memory getTimeZone(Environment env, Memory... args) {
return new ObjectMemory(new WrapTimeZone(env, timeZone));
}
@Signature(@Arg(value = "time", nativeType = WrapTime.class))
public Memory compare(Environment env, Memory... args) {
return LongMemory.valueOf(calendar.compareTo(args[0].toObject(WrapTime.class).calendar));
}
@Signature({
@Arg(value = "timeZone", nativeType = WrapTimeZone.class, optional = @Optional("null")),
@Arg(value = "locale", nativeType = WrapLocale.class, optional = @Optional("NULL"))
})
public static Memory now(Environment env, Memory... args) {
Locale aLocale = args[1].isNull() ? Locale.ENGLISH : args[1].toObject(WrapLocale.class).getLocale();
TimeZone zone = WrapTimeZone.getTimeZone(env, args[0]);
return new ObjectMemory(new WrapTime(env, Calendar.getInstance(zone, aLocale).getTime(), zone, aLocale));
}
@Signature(@Arg(value = "timeZone", nativeType = WrapTimeZone.class))
public Memory withTimezone(Environment env, Memory... args) {
TimeZone zone = WrapTimeZone.getTimeZone(env, args[0]);
return new ObjectMemory(new WrapTime(env, date, zone, locale));
}
@Signature(@Arg(value = "locale", nativeType = WrapLocale.class))
public Memory withLocale(Environment env, Memory... args) {
return new ObjectMemory(new WrapTime(env, date, timeZone, args[0].toObject(WrapLocale.class).getLocale()));
}
@Signature(@Arg(value = "args", type = HintType.ARRAY))
public Memory add(Environment env, Memory... args) {
ArrayMemory arg = args[0].toValue(ArrayMemory.class);
Memory year = arg.getByScalar("year");
Memory month = arg.getByScalar("month");
Memory day = arg.getByScalar("day");
Memory hour = arg.getByScalar("hour");
Memory min = arg.getByScalar("min");
Memory sec = arg.getByScalar("sec");
Memory millis = arg.getByScalar("millis");
Calendar calendar1 = (Calendar) calendar.clone();
if (year != null)
calendar1.add(Calendar.YEAR, year.toInteger());
if (month != null)
calendar1.add(Calendar.MONTH, month.toInteger());
if (day != null)
calendar1.add(Calendar.DAY_OF_MONTH, day.toInteger());
if (hour != null)
calendar1.add(Calendar.HOUR_OF_DAY, hour.toInteger());
if (min != null)
calendar1.add(Calendar.MINUTE, min.toInteger());
if (sec != null)
calendar1.add(Calendar.SECOND, sec.toInteger());
if (millis != null)
calendar1.add(Calendar.MILLISECOND, millis.toInteger());
return new ObjectMemory(new WrapTime(env, calendar1.getTime(), timeZone));
}
@Signature
public Memory __toString(Environment env, Memory... args) {
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(timeZone);
return new StringMemory(isoFormat.format(date));
}
@Signature({
@Arg("format"),
@Arg(value = "locale", nativeType = WrapLocale.class, optional = @Optional("NULL"))
})
public Memory toString(Environment env, Memory... args) {
Locale aLocale = args[1].isNull() ? locale : args[1].toObject(WrapLocale.class).getLocale();
SimpleDateFormat format = new SimpleDateFormat(args[0].toString(), aLocale);
format.setTimeZone(timeZone);
return StringMemory.valueOf(format.format(date));
}
@Signature({
@Arg(value = "args", type = HintType.ARRAY)
})
public Memory replace(Environment env, Memory... args) {
ArrayMemory arg = args[0].toValue(ArrayMemory.class);
Memory year = arg.getByScalar("year");
Memory month = arg.getByScalar("month");
Memory day = arg.getByScalar("day");
Memory hour = arg.getByScalar("hour");
Memory min = arg.getByScalar("min");
Memory sec = arg.getByScalar("sec");
Memory millis = arg.getByScalar("millis");
Calendar calendar1 = (Calendar) calendar.clone();
if (year != null)
calendar1.set(Calendar.YEAR, year.toInteger());
if (month != null)
calendar1.set(Calendar.MONTH, month.toInteger() - 1);
if (day != null)
calendar1.set(Calendar.DATE, day.toInteger());
if (hour != null)
calendar1.set(Calendar.HOUR_OF_DAY, hour.toInteger());
if (min != null)
calendar1.set(Calendar.MINUTE, min.toInteger());
if (sec != null)
calendar1.set(Calendar.SECOND, sec.toInteger());
if (millis != null)
calendar1.set(Calendar.MILLISECOND, millis.toInteger());
return new ObjectMemory(new WrapTime(env, calendar1.getTime(), calendar1.getTimeZone()));
}
@FastMethod
@Signature
public static Memory millis(Environment env, Memory... args) {
return LongMemory.valueOf(System.currentTimeMillis());
}
@FastMethod
@Signature
public static Memory seconds(Environment env, Memory... args) {
return LongMemory.valueOf(System.currentTimeMillis() / 1000);
}
@FastMethod
@Signature
public static Memory nanos(Environment env, Memory... args) {
return LongMemory.valueOf(System.nanoTime());
}
@Signature({
@Arg(value = "timeZone", nativeType = WrapTimeZone.class, optional = @Optional("NULL")),
@Arg(value = "locale", nativeType = WrapLocale.class, optional = @Optional("NULL"))
})
public static Memory today(Environment env, Memory... args) {
Date date1 = new Date();
Locale aLocale = args[1].isNull() ? Locale.ENGLISH : args[1].toObject(WrapLocale.class).getLocale();
Calendar calendar = Calendar.getInstance(
WrapTimeZone.getTimeZone(env, args[0]),
aLocale
);
calendar.setTime(date1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.MILLISECOND, 0);
return new ObjectMemory(new WrapTime(env, calendar.getTime(), calendar.getTimeZone(), aLocale));
}
@Signature({
@Arg(value = "args", type = HintType.ARRAY),
@Arg(value = "timeZone", nativeType = WrapTimeZone.class, optional = @Optional("null")),
@Arg(value = "locale", nativeType = WrapLocale.class, optional = @Optional("null"))
})
public static Memory of(Environment env, Memory... args) {
Locale aLocale = args[2].isNull() ? Locale.ENGLISH : args[2].toObject(WrapLocale.class).getLocale();
Calendar calendar = Calendar.getInstance(WrapTimeZone.getTimeZone(env, args[1]), aLocale);
Memory arg = args[0];
int year = arg.valueOfIndex("year").toInteger();
Memory m = arg.toValue(ArrayMemory.class).getByScalar("month");
int month = 1;
if (m != null)
month = m.toInteger();
int day = arg.valueOfIndex("day").toInteger();
if (day < 1)
day = 1;
int hour = arg.valueOfIndex("hour").toInteger();
int min = arg.valueOfIndex("min").toInteger();
int sec = arg.valueOfIndex("sec").toInteger();
calendar.set(year, month - 1, day, hour, min, sec);
calendar.set(Calendar.MILLISECOND, arg.valueOfIndex("millis").toInteger());
return new ObjectMemory(new WrapTime(env, calendar.getTime(), calendar.getTimeZone(), aLocale));
}
@Override
public boolean __equal(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) == 0;
}
@Override
public boolean __identical(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) == 0 && timeZone.getID().equals(iObject.timeZone.getID());
}
@Override
public boolean __greater(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) > 0;
}
@Override
public boolean __greaterEq(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) >= 0;
}
@Override
public boolean __smaller(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) < 0;
}
@Override
public boolean __smallerEq(WrapTime iObject) {
return calendar.compareTo(iObject.calendar) <= 0;
}
@Signature
private Memory __clone(Environment env, Memory... args) {
return Memory.NULL;
}
}