[Linux, Win?, Mac?] DateTime mit Locales

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

[Linux, Win?, Mac?] DateTime mit Locales

Beitrag von NicTheQuick »

Hi Leute,

das hier ist so ein Proof of Concept für die Darstellung eines Datums und der Zeit mittels locales. Es funktioniert bisher gut, aber es gibt auch einen Crash, der als Beispiel ganz unten auskommentiert ist und den ich nicht verstehe. Vielleicht hat da jemand eine Idee.

Ich möchte das ganze auch noch auf Zahlen und Geldbeträge ausweiten. Für Linux kein Problem, aber ich könnte Hilfe für die anderen Betriebssysteme gebrauchen. Und dann mache ich ein Module daraus. Wie gefällt euch die Parameterübergabe? Soll ich vielleicht das setlocale() sogar auslagern, sodass man es einmal setzt und dann kann man beliebig viele Date-Funktionen aufrufen?

Wichtig ist, dass es nur mit locales funktioniert, die auch installiert sind. Ihr findet das unter Linux heraus, indem ihr im Terminal "locale -a" eingibt. Neu hinzufügen für z.B. Russisch geht so:

Code: Alles auswählen

sudo locale-gen ru_RU.UTF-8
sudo update-locale
Und wenn ihr nicht wisst, was ihr noch installieren könntet, gibt es hier eine Liste: /usr/share/i18n/SUPPORTE

Hier aber nun der Code.

Code: Alles auswählen

Structure tm
	tm_sec.l	; seconds
	tm_min.l	; minutes
	tm_hour.l	; hours
	tm_mday.l	; day of the month
	tm_mon.l	; month
	tm_year.l	; number of years since 1900
	tm_wday.l	; day of the week
	tm_yday.l	; day in the year
	tm_isdst.l	; daylight saving time
EndStructure

Enumeration 1
	#LC_ALL
	#LC_COLLATE
	#LC_CTYPE
	#LC_MONETARY
	#LC_NUMERIC
	#LC_TIME
EndEnumeration

Import ""
	time(*rawtime)
	localtime.i(*rawtime)
	strftime(*dest, maxsize.l, format.p-utf8, *timeprt.tm)
	setlocale(t.i, locale.p-ascii)
EndImport

Procedure.s localDateTime(date.q, mask.s = "%x %X", locale.s = "")
	Protected bufferSize.i = 12
	Protected *result = AllocateMemory(bufferSize), *tResult
	Protected tm.tm, *oldLocale, oldLocale.s, result.s
	tm\tm_sec = Second(date)
	tm\tm_min = Minute(date)
	tm\tm_hour = Hour(date)
	tm\tm_mday = Day(date)
	tm\tm_mon = Month(date) - 1
	tm\tm_year = Year(date) - 1900
	tm\tm_wday = DayOfWeek(date)
	tm\tm_yday = DayOfYear(date) - 1
	tm\tm_isdst = 0
	
	*oldLocale = setlocale(#LC_TIME, locale)
	If Not *oldLocale
		DebuggerWarning("Locale could not be set: " + locale)
	Else
		oldLocale = PeekS(*oldLocale, -1, #PB_Ascii)
	EndIf
	
	
	While Not strftime(*result, bufferSize, mask, @tm)
		bufferSize * 2
		*tResult = ReAllocateMemory(*result, bufferSize, #PB_Memory_NoClear)
		If Not *result
			DebuggerWarning("Could not allocate enough memory for datetime conversion.")
			Break
		EndIf
		*result = *tResult
	Wend
	
	result = PeekS(*result, -1, #PB_UTF8)
	
	FreeMemory(*result)
	
	If *oldLocale
		setlocale(#LC_TIME, oldLocale)
	EndIf
	
	ProcedureReturn result
EndProcedure

Debug localDateTime(Date(2018, 3, 3, 0, 0, 0), "Heute ist %A. Wir haben %X Uhr und es ist der %x. Der Monat ist %B.", "de_DE.UTF8")

; Das hier crasht :(
;Debug localDateTime(Date(), "%c", "de_DE.UTF8")
Bild
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von Sicro »

Code: Alles auswählen

*tResult = ReAllocateMemory(*result, bufferSize, #PB_Memory_NoClear)
If Not *result
ändern zu:

Code: Alles auswählen

*tResult = ReAllocateMemory(*result, bufferSize, #PB_Memory_NoClear)
If Not *tResult
Das Problem ist damit aber leider noch nicht gelöst.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
kapege
Beiträge: 39
Registriert: 28.12.2004 17:35
Computerausstattung: AMD Ryzen 7 3700X 8-Core Processor 3.60 GHz
Windows 10 Pro 64bit
14 GB Ram

PureBasic 6.00 LTS (Windows - x64)
Wohnort: Trostberg

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von kapege »

bei mir crasht nichts.
Win 7 64bit, Purebasic 5.61 64bit


Debug localDateTime(Date(2018, 3, 3, 0, 0, 0), "Heute ist %A. Wir haben %X Uhr und es ist der %x. Der Monat ist %B.", "de_DE.UTF8")

; Das hier crasht :(
Debug localDateTime(Date(), "%c", "de_DE.UTF8")

Heute ist Saturday. Wir haben 00:00:00 Uhr und es ist der 03/03/18. Der Monat ist March.
06/30/18 07:26:34
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von NicTheQuick »

Moment, das läuft auf Windows 7? :shock: Ist das etwa kompatibel? Es kommt trotzdem das falsche Ergebnis bei dir raus. Mit de_DE sollte natürlich alles deutsch sein.
Bild
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von mk-soft »

Im Header Datei von locale.h stehen bei mir andere Konstanten.
#LC_ALL = 0
#LC_COLLATE = 1
#LC_CTYPE = 2
#LC_MONETARY = 3
#LC_NUMERIC = 4
#LC_TIME = 5
#LC_MESSAGES = 6
Bei MacOS funktioniert es nicht mit der C++ Lib. Das setzen von locale auf andere Sprachen schlägt fehl.
Es wird nur "C" und "POSIX" akzeptiert.

P.S
Windows schlägt auch fehl...

UND

Linux schlägt fehl... Unter Linux steht locale schon auf Userdefault.

Test

Code: Alles auswählen

#LC_ALL       = 0
#LC_COLLATE   = 1
#LC_CTYPE     = 2
#LC_MONETARY  = 3
#LC_NUMERIC   = 4
#LC_TIME      = 5
#LC_MESSAGES  = 6

; Enumeration 1
;    #LC_ALL
;    #LC_COLLATE
;    #LC_CTYPE
;    #LC_MONETARY
;    #LC_NUMERIC
;    #LC_TIME
; EndEnumeration

Import ""
   setlocale(t.i, *locale)
EndImport

*oldlocale = setlocale(#LC_TIME, 0)
Debug "Default: " + PeekS(*oldlocale, -1, #PB_Ascii)

*locale = Ascii("")
Debug setlocale(#LC_TIME, *locale)
FreeMemory(*locale)

*locale = Ascii("de-DE.UTF8")
Debug setlocale(#LC_ALL, *locale)
FreeMemory(*locale)

*locale = Ascii("de-DE")
Debug setlocale(#LC_TIME, *locale)
FreeMemory(*locale)

*locale = Ascii("en-EN.UTF-8")
Debug setlocale(#LC_TIME, *locale)
FreeMemory(*locale)

*locale = Ascii("POSIX")
Debug setlocale(#LC_TIME, *locale)
FreeMemory(*locale)

*locale = Ascii("C")
Debug setlocale(#LC_TIME, *locale)
FreeMemory(*locale)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von mk-soft »

Wie es aus sieht kann man nur zwischen Userdefault und "C" mit setlocale wechseln.
Nur bei MacOS geht es nicht.

Update 'C'

Code: Alles auswählen

Structure tm
  tm_sec.l   ; seconds
  tm_min.l   ; minutes
  tm_hour.l  ; hours
  tm_mday.l  ; day of the month
  tm_mon.l   ; month
  tm_year.l  ; number of years since 1900
  tm_wday.l  ; day of the week
  tm_yday.l  ; day in the year
  tm_isdst.l ; daylight saving time
EndStructure

#LC_ALL       = 0
#LC_COLLATE   = 1
#LC_CTYPE     = 2
#LC_MONETARY  = 3
#LC_NUMERIC   = 4
#LC_TIME      = 5
#LC_MESSAGES  = 6

ImportC ""
  time(*rawtime)
  localtime.i(*rawtime)
  strftime(*dest, maxsize.l, format.p-utf8, *timeprt.tm)
  setlocale(t.i, *locale)
EndImport

Procedure.s localDateTime(date.q, mask.s = "%x %X", locale.s="")
  Protected bufferSize.i = 12, *locale
  Protected *result = AllocateMemory(bufferSize), *tResult
  Protected tm.tm, *oldLocale, oldLocale.s, result.s
  tm\tm_sec = Second(date)
  tm\tm_min = Minute(date)
  tm\tm_hour = Hour(date)
  tm\tm_mday = Day(date)
  tm\tm_mon = Month(date) - 1
  tm\tm_year = Year(date) - 1900
  tm\tm_wday = DayOfWeek(date)
  tm\tm_yday = DayOfYear(date) - 1
  tm\tm_isdst = 0
  
  *locale = Ascii(locale)
  
  *oldLocale = setlocale(#LC_TIME, 0)
  If Not setlocale(#LC_TIME, *locale)
    DebuggerWarning("Locale could not be set: " + locale)
    Debug "No set"
  EndIf
  
  
  While Not strftime(*result, bufferSize, mask, @tm)
    bufferSize * 2
    *tResult = ReAllocateMemory(*result, bufferSize, #PB_Memory_NoClear)
    If Not *result
      DebuggerWarning("Could not allocate enough memory for datetime conversion.")
      Break
    EndIf
    *result = *tResult
  Wend
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    result = PeekS(*result, -1, #PB_Ascii)
  CompilerElse
    result = PeekS(*result, -1, #PB_UTF8)
  CompilerEndIf
  
  FreeMemory(*result)
  
  If *oldLocale
    setlocale(#LC_TIME, *oldLocale)
  EndIf
  
  FreeMemory(*locale)
  
  ProcedureReturn result
EndProcedure

Debug localDateTime(Date(2018, 3, 28, 12, 0, 0), "Heute ist %A. Wir haben %X Uhr und es ist der %x. Der Monat ist %B.")
Debug localDateTime(Date(2018, 3, 28, 12, 0, 0), "Heute ist %A. Wir haben %X Uhr und es ist der %x. Der Monat ist %B.", "C")
Zuletzt geändert von mk-soft am 30.06.2018 21:46, insgesamt 1-mal geändert.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
#NULL
Beiträge: 2235
Registriert: 20.04.2006 09:50

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von #NULL »

geht :D , Ubuntu 16.04

Code: Alles auswählen

Heute ist Samstag. Wir haben 00:00:00 Uhr und es ist der 03.03.2018. Der Monat ist März.
Sa 30 Jun 2018 15:00:20 d
my pb stuff..
Bild..jedenfalls war das mal so.
Benutzeravatar
_JON_
Beiträge: 389
Registriert: 30.03.2010 15:24

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von _JON_ »

ImportC "" ... sonst crashed es mit 32bit Compiler.
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von Sicro »

NicTheQuick hat geschrieben:Moment, das läuft auf Windows 7? :shock: Ist das etwa kompatibel?
Du importierst ja die Befehle von C++ ... :-)
#NULL hat geschrieben:geht :D , Ubuntu 16.04

Code: Alles auswählen

Heute ist Samstag. Wir haben 00:00:00 Uhr und es ist der 03.03.2018. Der Monat ist März.
Sa 30 Jun 2018 15:00:20 d
So sieht das bei mir auch aus, wenn ich die Debugs zu einem MessageRequester abändere und den Debugger abschalte.
Das "d" am Ende deutet aber darauf hin, dass die Ausgabe abgeschnitten und somit unvollständig ist.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: [Linux, Win?, Mac?] DateTime mit Locales

Beitrag von NicTheQuick »

Muss ich mir noch mal angucken. Komme wohl erst wieder am Montag dazu.
Bild
Antworten