Improve compatibility of os.date() function

This commit is contained in:
James Roseborough
2013-07-14 17:28:38 +00:00
parent db1c7a17b2
commit 9179e74e36
4 changed files with 67 additions and 65 deletions

View File

@@ -24,7 +24,6 @@ package org.luaj.vm2.lib;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.luaj.vm2.Buffer;
import org.luaj.vm2.Globals;
@@ -139,8 +138,23 @@ public class OsLib extends TwoArgFunction {
case CLOCK:
return valueOf(clock());
case DATE: {
String s = args.optjstring(1, null);
double t = args.optdouble(2,-1);
String s = args.optjstring(1, "%c");
double t = args.isnumber(2)? args.todouble(2): time(null);
if (s.equals("*t")) {
Calendar d = Calendar.getInstance();
d.setTime(new Date((long)(t*1000)));
LuaTable tbl = LuaValue.tableOf();
tbl.set("year", LuaValue.valueOf(d.get(Calendar.YEAR)));
tbl.set("month", LuaValue.valueOf(d.get(Calendar.MONTH)+1));
tbl.set("day", LuaValue.valueOf(d.get(Calendar.DAY_OF_MONTH)));
tbl.set("hour", LuaValue.valueOf(d.get(Calendar.HOUR)));
tbl.set("min", LuaValue.valueOf(d.get(Calendar.MINUTE)));
tbl.set("sec", LuaValue.valueOf(d.get(Calendar.SECOND)));
tbl.set("wday", LuaValue.valueOf(d.get(Calendar.DAY_OF_WEEK)));
tbl.set("yday", LuaValue.valueOf(d.get(Calendar.DAY_OF_YEAR)));
tbl.set("isdst", LuaValue.valueOf(isDaylightSavingsTime(d)));
return tbl;
}
return valueOf( date(s, t==-1? time(null): t) );
}
case DIFFTIME:
@@ -164,8 +178,9 @@ public class OsLib extends TwoArgFunction {
String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all"));
return s!=null? valueOf(s): NIL;
}
case TIME:
case TIME: {
return valueOf(time(args.arg1().isnil()? null: args.checktable(1)));
}
case TMPNAME:
return valueOf(tmpname());
}
@@ -215,13 +230,17 @@ public class OsLib extends TwoArgFunction {
* formatted according to the given string format.
*/
public String date(String format, double time) {
Calendar d = Calendar.getInstance();
d.setTime(new Date((long)(time*1000)));
if (format.startsWith("!")) {
time -= timeZoneOffset(d);
d.setTime(new Date((long)(time*1000)));
format = format.substring(1);
}
byte[] fmt = format.getBytes();
final int n = fmt.length;
Buffer result = new Buffer(n);
byte c;
Date date = new Date((long)(time*1000));
Calendar d = Calendar.getInstance();
d.setTime(date);
for ( int i = 0; i < n; ) {
switch ( c = fmt[i++ ] ) {
case '\n':
@@ -234,8 +253,7 @@ public class OsLib extends TwoArgFunction {
if (i >= n) break;
switch ( c = fmt[i++ ] ) {
default:
result.append( (byte)'%' );
result.append( (byte)c );
LuaValue.argerror(1, "invalid conversion specifier '%"+c+"'");
break;
case '%':
result.append( (byte)'%' );
@@ -247,7 +265,6 @@ public class OsLib extends TwoArgFunction {
result.append(WeekdayName[d.get(Calendar.DAY_OF_WEEK)-1]);
break;
case 'b':
case 'h':
result.append(MonthNameAbbrev[d.get(Calendar.MONTH)]);
break;
case 'B':
@@ -256,22 +273,9 @@ public class OsLib extends TwoArgFunction {
case 'c':
result.append(date("%a %b %d %H:%M:%S %Y", time));
break;
case 'C':
result.append(String.valueOf((100000+d.get(Calendar.YEAR))/100).substring(2));
break;
case 'd':
result.append(String.valueOf(100+d.get(Calendar.DAY_OF_MONTH)).substring(1));
break;
case 'e': {
final String s = String.valueOf(d.get(Calendar.DAY_OF_MONTH));
if (s.length() < 2)
result.append((byte)' ');
result.append(s);
break;
}
case 'F':
result.append(date("%Y-%m-%d", time));
break;
case 'H':
result.append(String.valueOf(100+d.get(Calendar.HOUR_OF_DAY)).substring(1));
break;
@@ -290,30 +294,12 @@ public class OsLib extends TwoArgFunction {
case 'M':
result.append(String.valueOf(100+d.get(Calendar.MINUTE)).substring(1));
break;
case 'n':
result.append((byte)'\n');
break;
case 'p':
result.append(d.get(Calendar.HOUR_OF_DAY) < 12? "AM": "PM");
break;
case 'R':
result.append(date("%H:%M", time));
break;
case 'r': {
final String s = date("%I:%M:%S", time);
result.append(s);
result.append(d.get(Calendar.HOUR_OF_DAY) < 12? " am": " pm");
break;
}
case 'S':
result.append(String.valueOf(100+d.get(Calendar.SECOND)).substring(1));
break;
case 't':
result.append((byte)'\t');
break;
case 'u':
result.append(String.valueOf((d.get(Calendar.DAY_OF_WEEK)+5)%7+1));
break;
case 'U':
result.append(String.valueOf(weekNumber(d, 0)));
break;
@@ -324,11 +310,9 @@ public class OsLib extends TwoArgFunction {
result.append(String.valueOf(weekNumber(d, 1)));
break;
case 'x':
case 'D':
result.append(date("%m/%d/%y", time));
break;
case 'X':
case 'T':
result.append(date("%H:%M:%S", time));
break;
case 'y':
@@ -338,12 +322,13 @@ public class OsLib extends TwoArgFunction {
result.append(String.valueOf(d.get(Calendar.YEAR)));
break;
case 'z': {
final int tzo = d.getTimeZone().getRawOffset() / (60 * 1000);
result.append((tzo>0? "+": "") + String.valueOf(tzo));
final int tzo = timeZoneOffset(d) / 60;
final int a = Math.abs(tzo);
final String h = String.valueOf(100 + a / 60).substring(1);
final String m = String.valueOf(100 + a % 60).substring(1);
result.append((tzo>=0? "+": "-") + h + m);
break;
}
case 'Z':
break;
}
}
}
@@ -368,17 +353,33 @@ public class OsLib extends TwoArgFunction {
private int weekNumber(Calendar d, int startDay) {
Calendar y0 = beginningOfYear(d);
System.out.println("Time Date(time) " + d.getTime() + " y0 " + y0.getTime());
y0.set(Calendar.DAY_OF_MONTH, 1 + (startDay + 8 - y0.get(Calendar.DAY_OF_WEEK)) % 7);
if (y0.after(d)) {
y0.set(Calendar.YEAR, y0.get(Calendar.YEAR) - 1);
y0.set(Calendar.DAY_OF_MONTH, 1 + (startDay + 8 - y0.get(Calendar.DAY_OF_WEEK)) % 7);
System.out.println(" -> y0 " + y0.getTime());
}
long dt = d.getTime().getTime() - y0.getTime().getTime();
return 1 + (int) (dt / (7L * 24L * 3600L * 1000L));
}
private int timeZoneOffset(Calendar d) {
int localStandarTimeMillis = (
d.get(Calendar.HOUR_OF_DAY) * 3600 +
d.get(Calendar.MINUTE) * 60 +
d.get(Calendar.SECOND)) * 1000;
return d.getTimeZone().getOffset(
1,
d.get(Calendar.YEAR),
d.get(Calendar.MONTH),
d.get(Calendar.DAY_OF_MONTH),
d.get(Calendar.DAY_OF_WEEK),
localStandarTimeMillis) / 1000;
}
private boolean isDaylightSavingsTime(Calendar d) {
return timeZoneOffset(d) != d.getTimeZone().getRawOffset() / 1000;
}
/**
* This function is equivalent to the C function system.
* It passes command to be executed by an operating system shell.

View File

@@ -25,37 +25,21 @@ public class OsLibTest extends TestCase {
public void testStringDate_b() { t("%b", "Aug"); }
public void testStringDate_B() { t("%B", "August"); }
public void testStringDate_c() { t("%c", "Thu Aug 23 14:55:02 2001"); }
public void testStringDate_C() { t("%C", "20"); }
public void testStringDate_d() { t("%d", "23"); }
public void testStringDate_D() { t("%D", "08/23/01"); }
public void testStringDate_e() { t("%e", "23"); }
public void testStringDate_F() { t("%F", "2001-08-23"); }
public void testStringDate_g() { t("%g", "%g"); } // not implemented.
public void testStringDate_G() { t("%G", "%G"); } // not implemented.
public void testStringDate_h() { t("%h", "Aug"); }
public void testStringDate_H() { t("%H", "14"); }
public void testStringDate_I() { t("%I", "02"); }
public void testStringDate_j() { t("%j", "235"); }
public void testStringDate_m() { t("%m", "08"); }
public void testStringDate_M() { t("%M", "55"); }
public void testStringDate_n() { t("%n", "\n"); }
public void testStringDate_p() { t("%p", "PM"); }
public void testStringDate_r() { t("%r", "02:55:02 pm"); }
public void testStringDate_R() { t("%R", "14:55"); }
public void testStringDate_S() { t("%S", "02"); }
public void testStringDate_t() { t("%t", "\t"); }
public void testStringDate_T() { t("%T", "14:55:02"); }
public void testStringDate_u() { t("%u", "4"); }
public void testStringDate_U() { t("%U", "33"); }
public void testStringDate_V() { t("%V", "%V"); } // not implemented.
public void testStringDate_w() { t("%w", "4"); }
public void testStringDate_W() { t("%W", "34"); }
public void testStringDate_x() { t("%x", "08/23/01"); }
public void testStringDate_X() { t("%X", "14:55:02"); }
public void testStringDate_y() { t("%y", "01"); }
public void testStringDate_Y() { t("%Y", "2001"); }
public void testStringDate_z() { t("%z", "-480"); }
public void testStringDate_Z() { t("%Z", ""); }
public void testStringDate_Pct() { t("%%", "%"); }
static final double DAY = 24. * 3600.;

Binary file not shown.

View File

@@ -37,3 +37,20 @@ print( 'os.remove(q)', pcall( os.remove, q ) )
-- print( 'os.setlocale(nil,"all")', pcall( os.setlocale, nil, "all" ) )
print( 'os.setlocale("C")', pcall( os.setlocale, "C" ) )
print( 'os.exit', type(os.exit) )
-- os.date() formatting
local t = 1281364496 -- Aug 9, 2010, 2:34:56 PM (Monday)
local function p(s)
if pcall(os.date, s, t) then
print( "os.date('"..s.."', "..t..")", pcall(os.date, s, t))
end
end
for i= 65, 90 do
p('%'..string.char(i + 97 - 65))
p('%'..string.char(i))
end
local tbl = os.date('*t', t)
for i,k in ipairs({'year', 'month', 'day', 'hour', 'min', 'sec', 'wday', 'yday', 'isdst'}) do
local v = tbl[k]
print('k', type(k), k, 'v', type(v), v)
end