Jelajahi Sumber

Added stat64_(). Updated from/to epoch functions.

Brucey 2 tahun lalu
induk
melakukan
5a1b1047ea
3 mengubah file dengan 126 tambahan dan 15 penghapusan
  1. 9 3
      stdc.mod/stdc.bmx
  2. 107 2
      stdc.mod/stdc.c
  3. 10 10
      stdc.mod/tests/test.bmx

+ 9 - 3
stdc.mod/stdc.bmx

@@ -223,6 +223,7 @@ Function opendir_:Byte Ptr( path:String )
 Function closedir_:Int( dir:Byte Ptr )
 Function readdir_:String( dir:Byte Ptr )
 Function stat_:Int( path:String,st_mode:Int Var,st_size:Long Var,st_mtime:Int Var,st_ctime:Int Var,st_atime:Int Var )
+Function stat64_:Int( path:String,st_mode:Int Var,st_size:Long Var,st_mtime:Long Var,st_ctime:Long Var,st_atime:Long Var )
 Function system_:Int( cmd:String )
 Function utime_:Int( path:String, ty:Int, time:Long)
 
@@ -556,9 +557,10 @@ Struct SDateTime
 
 	If @fracNanoSecs is provided, it will be used to set the 'millisecond' field of the SDateTime instance.
 	The nanosecond fraction is effectively divided by a million to provide millisecond precision.
+	If @isLocal is set to #True, the epoch timestamp is assumed to be in local time, otherwise it is assumed to be in UTC.
 	End Rem
-	Function FromEpoch:SDateTime(epochSecs:Long, fracNanoSecs:Long = 0)
-		Return bmx_datetime_from_epoch(epochSecs, fracNanoSecs)
+	Function FromEpoch:SDateTime(epochSecs:Long, fracNanoSecs:Long = 0, isLocal:Int = False)
+		Return bmx_datetime_from_epoch(epochSecs, fracNanoSecs, isLocal:Int)
 	End Function
 
 	Rem
@@ -576,6 +578,10 @@ Struct SDateTime
 	returns: The equivalent date time in UTC, or the original date time if the conversion failed.
 	End Rem
 	Method ToUtc:SDateTime()
+		If utc Then
+			Return Self
+		End If
+
 		Local dt:SDateTime
 		Local res:Int = bmx_datetime_convert_to_utc(Self, dt)
 		If res = 0 Then
@@ -636,7 +642,7 @@ Private
 Extern "c"
 	Function bmx_datetime_iso8601:String(dt:SDateTime Var, showMillis:Int = False)
 	Function Startup()="bb_stdc_Startup"
-	Function bmx_datetime_from_epoch:SDateTime(epochSecs:Long, fracNanoSecs:Long)
+	Function bmx_datetime_from_epoch:SDateTime(epochSecs:Long, fracNanoSecs:Long, isLocal:Int)
 	Function bmx_current_datetime_format:String(format:String)
 	Function bmx_datetime_to_epoch:Long(dt:SDateTime Var)
 	Function bmx_datetime_convert_to_utc:Int(dt:SDateTime Var, dtUtc:SDateTime Var)

+ 107 - 2
stdc.mod/stdc.c

@@ -283,6 +283,38 @@ int stat_( BBString *path,int *t_mode,BBLONG *t_size,int *t_mtime,int *t_ctime,i
 	return 0;
 }
 
+int stat64_( BBString *path,int *t_mode,BBLONG *t_size,BBLONG *t_mtime,BBLONG *t_ctime,BBLONG *t_atime ){
+	int i;
+	struct _stati64 st;
+	
+	for( i=0;i<path->length;++i ){
+		if( path->buf[i]=='<' || path->buf[i]=='>' ) return -1;
+	}
+	
+	if( _bbusew ){
+		BBChar *p = bbStringToWString(path);
+		if( _wstati64( p,&st ) ) {
+			bbMemFree(p);
+			return -1;
+		}
+		bbMemFree(p);
+	}else{
+		char *p = bbStringToCString(path);
+		if( _stati64( p,&st ) ) {
+			bbMemFree(p);
+			return -1;
+		}
+		bbMemFree(p);
+	}
+
+	*t_mode=st.st_mode;
+	*t_size=st.st_size;
+	*t_mtime=st.st_mtime;
+	*t_ctime=st.st_ctime;
+	*t_atime=st.st_atime;
+	return 0;
+}
+
 int system_( BBString *cmd ){
 	int res;
 	PROCESS_INFORMATION pi={0};
@@ -491,6 +523,22 @@ int stat_( BBString *path,int *t_mode,BBLONG *t_size,int *t_mtime,int *t_ctime,i
 	return 0;
 }
 
+int stat64_( BBString *path,int *t_mode,BBLONG *t_size,BBLONG *t_mtime,BBLONG *t_ctime,BBLONG *t_atime ){
+	struct stat st;
+	char *p = bbStringToUTF8String( path );
+	if( stat( p,&st ) ) {
+		bbMemFree(p);
+		return -1;
+	}
+	bbMemFree(p);
+	*t_mode=st.st_mode;
+	*t_size=st.st_size;
+	*t_mtime=st.st_mtime;
+	*t_ctime=st.st_ctime;
+	*t_atime=st.st_atime;
+	return 0;
+}
+
 int utime_( BBString *path, int type, BBLONG time){
 	struct utimbuf times = {0,0};
 
@@ -1004,8 +1052,51 @@ void bmx_current_datetime(SDateTime * dt, int utc) {
 }
 #endif
 
-SDateTime bmx_datetime_from_epoch(BBLONG epochTimeSecs, BBLONG fracNanoseconds) {
+int bmx_datetime_from_local_epoch(BBLONG epoch, SDateTime* dt) {
+    struct tm* local;
+#if defined(__linux__) || defined(__APPLE__)
+    struct tm result;
+    local = localtime_r(&epoch, &result);
+#elif defined(_WIN32) || defined(_WIN64)
+    local = localtime(&epoch);
+#else
+    return -1; // Platform not supported
+#endif
+
+    if (!local) {
+        return -1;
+    }
+
+    dt->year = local->tm_year + 1900;
+    dt->month = local->tm_mon + 1;
+    dt->day = local->tm_mday;
+    dt->hour = local->tm_hour;
+    dt->minute = local->tm_min;
+    dt->second = local->tm_sec;
+    dt->millisecond = 0;
+    dt->utc = 0; // This is local time
+#if defined(__linux__) || defined(__APPLE__)
+    dt->offset = local->tm_gmtoff / 60; // 'tm_gmtoff' holds seconds east of UTC
+    dt->dst = local->tm_isdst;
+#elif defined(_WIN32) || defined(_WIN64)
+    dt->offset = -bmx_calc_timeoffset_mins(dt); // - is because Windows returns minutes west of UTC
+#endif
+    return 0;
+}
+
+SDateTime bmx_datetime_from_epoch(BBLONG epochTimeSecs, BBLONG fracNanoseconds, int isLocalTime) {
     SDateTime dt;
+
+	if (isLocalTime) {
+		int res = bmx_datetime_from_local_epoch(epochTimeSecs, &dt);
+
+		if (res == 0) {
+			dt.millisecond = fracNanoseconds / 1000000;
+		}
+
+		return dt;
+	}
+
     struct tm timeinfo;
 
 #if defined(_WIN32) || defined(_WIN64)
@@ -1081,7 +1172,21 @@ time_t bmx_datetime_to_time_t(SDateTime * dt) {
 }
 
 BBLONG bmx_datetime_to_epoch(SDateTime * dt) {
-	return (BBLONG)bmx_datetime_to_time_t(dt);
+	if (dt->utc) {
+		return (BBLONG)bmx_datetime_to_time_t(dt);
+	}
+
+	struct tm t;
+
+	t.tm_year = dt->year - 1900;
+	t.tm_mon = dt->month - 1;
+	t.tm_mday = dt->day;
+	t.tm_hour = dt->hour;
+	t.tm_min = dt->minute;
+	t.tm_sec = dt->second;
+	t.tm_isdst = dt->dst;
+
+	return (BBLONG)mktime(&t);
 }
 
 int bmx_datetime_convert_to_utc(const SDateTime* dt, SDateTime* dt_utc) {

+ 10 - 10
stdc.mod/tests/test.bmx

@@ -89,16 +89,16 @@ Type TSDateTimeTest Extends TTest
 
 	Method AssertSDateTimeEquals( expected:SDateTime, actual:SDateTime )
 
-		AssertEquals( expected.year, actual.year )
-		AssertEquals( expected.month, actual.month )
-		AssertEquals( expected.day, actual.day )
-		AssertEquals( expected.hour, actual.hour )
-		AssertEquals( expected.minute, actual.minute )
-		AssertEquals( expected.second, actual.second )
-		AssertEquals( expected.milliSecond, actual.milliSecond )
-		AssertEquals( expected.utc, actual.utc )
-		AssertEquals( expected.offset, actual.offset )
-		AssertEquals( expected.dst, actual.dst )
+		AssertEquals( expected.year, actual.year, "year" )
+		AssertEquals( expected.month, actual.month, "month" )
+		AssertEquals( expected.day, actual.day, "day" )
+		AssertEquals( expected.hour, actual.hour, "hour" )
+		AssertEquals( expected.minute, actual.minute, "minute" )
+		AssertEquals( expected.second, actual.second, "second" )
+		AssertEquals( expected.milliSecond, actual.milliSecond, "millisecond" )
+		AssertEquals( expected.utc, actual.utc, "utc" )
+		AssertEquals( expected.offset, actual.offset, "offset" )
+		AssertEquals( expected.dst, actual.dst, "dst" )
 
 	End Method
 End Type