Quellcode durchsuchen

Merge pull request #55 from bmx-ng/task/sdatetime-fromepoch

Added SDateTime FromEpoch function.
Brucey vor 2 Jahren
Ursprung
Commit
b2aed04e95
2 geänderte Dateien mit 90 neuen und 25 gelöschten Zeilen
  1. 26 10
      stdc.mod/stdc.bmx
  2. 64 15
      stdc.mod/stdc.c

+ 26 - 10
stdc.mod/stdc.bmx

@@ -431,7 +431,7 @@ Function bmx_stdc_getpeername:Int(socket:Long, port:Int Var, address:String Var)
 'time
 
 Function time_:Int( time:Byte Ptr )
-Function localtime_:Byte Ptr( time:Byte Ptr )
+Function localtime_:Byte Ptr( time:Byte Ptr ) ' note : not thread safe
 Function strftime_:Int( buf:Byte Ptr,size:Int,fmt$,time:Byte Ptr )
 
 ?Not macos
@@ -510,11 +510,31 @@ Struct SDateTime
 	End Method
 
 	Rem
-	bbdoc: Returns a string representation of the date time in ISO 8601 format.
+	bbdoc: Returns a string representation in ISO 8601 format.
+	about: ISO 8601 is an international standard covering the exchange of date- and time-related data.
+	It was issued by the International Organization for Standardization (ISO) and provides a well-defined method of representing dates and
+	times in a way that avoids ambiguity. 
+
+	An example of a date in ISO 8601 format is "2023-06-24T18:30:00Z", representing 6:30 pm on June 24, 2023, in Coordinated Universal Time (UTC).
+
+	If @showMillis is set to #True, the output string will include millisecond precision. For instance, "2023-06-24T18:30:00.123Z"
+	where "123" represents milliseconds.
 	End Rem
 	Method ToIso8601:String(showMillis:Int = False)
 		Return bmx_datetime_iso8601(Self, showMillis)
 	End Method
+
+	Rem
+	bbdoc: Returns an instance of #SDateTime representing the date and time corresponding to the given epoch timestamp.
+	about: The 'epoch' refers to the Unix epoch, which is a system for describing a point in time, defined as the number of seconds
+	that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, minus the number of leap seconds. 
+
+	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.
+	End Rem
+	Function FromEpoch:SDateTime(epochSecs:Long, fracNanoSecs:Long = 0)
+		Return bmx_datetime_from_epoch(epochSecs, fracNanoSecs)
+	End Function
 End Struct
 
 Rem
@@ -549,10 +569,7 @@ You can use these parameters together:<br/>
 CurrentDate("Month: %%a Day: %%d")<br/>
 End Rem
 Function CurrentDate$(_format$="%d %b %Y")
-	Local time:Byte[256],buff:Byte[256]
-	time_(time)
-	strftime_(buff,256,_format,localtime_( time ))
-	Return String.FromCString(buff)
+	Return bmx_current_datetime_format(_format)
 End Function
 
 Rem
@@ -562,10 +579,7 @@ about:
 Returns the current time in the format: HH:MM:SS (i.e. 14:31:57).
 End Rem
 Function CurrentTime$()
-	Local time:Byte[256],buff:Byte[256]
-	time_(time)
-	strftime_( buff,256,"%H:%M:%S",localtime_( time ) );
-	Return String.FromCString(buff)
+	Return bmx_current_datetime_format("%H:%M:%S")
 End Function
 
 Private
@@ -573,6 +587,8 @@ 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_current_datetime_format:String(format:String)
 End Extern
 
 Startup

+ 64 - 15
stdc.mod/stdc.c

@@ -956,19 +956,19 @@ void bmx_current_datetime(SDateTime * dt, int utc) {
 #else
 int bmx_calc_timeoffset_mins() {
 	time_t rawtime;
-    struct tm *local_tm, *utc_tm;
+    struct tm local_tm, utc_tm;
 
 	time(&rawtime);
-    local_tm = localtime(&rawtime);
-    utc_tm = gmtime(&rawtime);
+	localtime_r(&rawtime, &local_tm);
+	gmtime_r(&rawtime, &utc_tm);
 
     // Calculate the time difference in minutes
-    int diff_minutes = (local_tm->tm_hour - utc_tm->tm_hour) * 60 + (local_tm->tm_min - utc_tm->tm_min);
+    int diff_minutes = (local_tm.tm_hour - utc_tm.tm_hour) * 60 + (local_tm.tm_min - utc_tm.tm_min);
 
     // Adjust the difference if crossing a day boundary
-    if (local_tm->tm_yday < utc_tm->tm_yday) {
+    if (local_tm.tm_yday < utc_tm.tm_yday) {
         diff_minutes -= 24 * 60;
-    } else if (local_tm->tm_yday > utc_tm->tm_yday) {
+    } else if (local_tm.tm_yday > utc_tm.tm_yday) {
         diff_minutes += 24 * 60;
     }
 
@@ -977,28 +977,77 @@ int bmx_calc_timeoffset_mins() {
 
 void bmx_current_datetime(SDateTime * dt, int utc) {
     struct timespec ts;
-    struct tm *tm;
+    struct tm tm;
 
 	clock_gettime(CLOCK_REALTIME, &ts);
 
     if (utc) {
-        tm = gmtime(&ts.tv_sec);
+        gmtime_r(&ts.tv_sec, &tm);
     } else {
-        tm = localtime(&ts.tv_sec);
+        localtime_r(&ts.tv_sec, &tm);
     }
 
-    dt->year = tm->tm_year + 1900;
-    dt->month = tm->tm_mon + 1;
-    dt->day = tm->tm_mday;
-    dt->hour = tm->tm_hour;
-    dt->minute = tm->tm_min;
-    dt->second = tm->tm_sec;
+    dt->year = tm.tm_year + 1900;
+    dt->month = tm.tm_mon + 1;
+    dt->day = tm.tm_mday;
+    dt->hour = tm.tm_hour;
+    dt->minute = tm.tm_min;
+    dt->second = tm.tm_sec;
     dt->millisecond = ts.tv_nsec / 1000000;
     dt->utc = utc;
     dt->offset = utc ? 0 : bmx_calc_timeoffset_mins();
 }
 #endif
 
+SDateTime bmx_datetime_from_epoch(BBLONG epochTimeSecs, BBLONG fracNanoseconds) {
+    SDateTime dt;
+    struct tm timeinfo;
+
+#if defined(_WIN32) || defined(_WIN64)
+    gmtime_s(&timeinfo, &epochTimeSecs);
+#else
+    gmtime_r(&epochTimeSecs, &timeinfo);
+#endif
+
+    dt.year = timeinfo.tm_year + 1900;
+    dt.month = timeinfo.tm_mon + 1;
+    dt.day = timeinfo.tm_mday;
+    dt.hour = timeinfo.tm_hour;
+    dt.minute = timeinfo.tm_min;
+    dt.second = timeinfo.tm_sec;
+
+    dt.millisecond = fracNanoseconds / 1000000;
+
+    dt.utc = 1;
+    dt.offset = 0;
+
+    return dt;
+}
+
+BBString * bmx_current_datetime_format(BBString * format) {
+	struct tm tm;
+	time_t rawtime;
+	char buf[256];
+
+	unsigned char * f = bbStringToUTF8String(format);
+
+	time(&rawtime);
+    
+#if defined(_WIN32) || defined(_WIN64)
+    localtime_s(&tm, &rawtime);
+#else
+    localtime_r(&rawtime, &tm);
+#endif
+
+    strftime(buf, sizeof(buf), f, &tm);
+
+	BBString * res = bbStringFromUTF8String(buf);
+
+    bbMemFree(f);
+
+	return res;
+}
+
 BBString * bmx_datetime_iso8601(const SDateTime *dt, int showMillis) {
 	char buf[32];
 	if (dt->utc) {