Which date format does VarToDateTime(VarDateFromStr) use? - windows

I've been having problems lately with date conversion lately. Some workstations my application run on don't convert string to date correctly.
I tracked the issue down to VarDateFromStr that doesn't seem to be checking LOCALE_SSHORTDATE to make the conversion. I was wondering if anyone knew what it DID check for the conversion. Or does the different behavior only linked to different DLL version?
GetLocaleStr(GetThreadLocale, LOCALE_SSHORTDATE, 'm/d/yy'); // returns 'dd-MM-yyyy'
FormatDateTime('dd-MM-yyyy', VarToDateTime('05-11-2010')); //returns '11-05-2010'
EDIT:
I've been told that changing the short date format (in the control panel) from 'dd-MM-yyyy' to whatever and back to 'dd-MM-yyyy' fixed the problem. I still have to verify this though.
EDIT2: Kindda forgot to mention, the problem has only been confirmed on WinXP SP3 yet.

Ken, the VarToDateTime function internally calls the VarDateFromStr function wich uses the VAR_LOCALE_USER_DEFAULT constant to format the date.
to determine wich format contains the VAR_LOCALE_USER_DEFAULT you can use this code
var
FormatSettings : TFormatSettings;
begin
GetLocaleFormatSettings(VAR_LOCALE_USER_DEFAULT, formatSettings);
ShowMessage('VarToDateTime is using this format to convert dates '+formatSettings.ShortDateFormat);
end;
now to avoid your problem you can convert your variant value to string and then to datetime using the StrToDateTime function
var
v : variant;
FormatSettings : TFormatSettings;
Begin
v:='05-11-2010';//this is your variant.
FormatSettings.ShortDateFormat:='dd-mm-yyyy';//use this format in the conversion
ShowMessage(FormatDateTime('dd-MM-yyyy', StrToDateTime(V,FormatSettings)));
end;

Related

How to remove time from date time in VB6

i am currently working with VB6, and i have this value of date that is like this:
2022-02-26T12:06:10+02:00
I followed this url too
VB6: How to remove the Time part from Date type
but doesnt work especially the last one still shows the date as
2022-02-26T12:06:10+02:00
This is my code
Dim tdate As String
tdate = format$("2022-02-26T12:06:10+02:00" , "m/d/yyyy")
and the output is still 2022-02-26T12:06:10+02:00
Your input is a string in ISO8601 format. As its a string in a fixed format the easiest way is to just chop off the first 10 characters.
isoDateTimeString = "2022-02-26T12:06:10+02:00"
To get the date part as another string:
Dim dateAsString As String
dateAsString = Left$(isoDateTimeString, 10)
'// for 2022-02-26
Or to get it as a Date type:
Dim dateAsDateType As Date
dateAsDateType = CDate(Left$(isoDateTimeString, 10))
'// for 26/02/2022 (or whatever your locale format is)
In VB6 I've always found that the easiest way to deal with time/date values is to cast them as a Double (simply declare a variable as type Double, then assign the value from whatever source). Then, simply deal with either the integer part (days) or the fractional part (fractional days). For example, seconds are just TimeStamp/86400.0, etc. When a variable is declared as Date, it's actually stored as a Double, so I just use that as my basic TimeStamp type. VB is pretty good about re-formatting into a time/date string when printing, and it makes time-based calculations really straight-forward.

Convert AnsiString to UnicodeString in Lazarus with FreePascal

I found similar topics here but none of them had the solution to my question, so I am asking it in a new thread.
Couple of days ago, I changed the format the preferences of an application I am developing is saved, from INI to JSON.
I use the jsonConf unit for this.
A sample of the code I use to save a key-value pair in the file would be like below.
Procedure TMyClass.SaveSettings();
var
c: TJSONConfig;
begin
c:= TJSONConfig.Create(nil);
try
c.Filename:= m_settingsFilePath;
c.SetValue('/Systems/CustomName', m_customName);
finally
c.Free;
end;
end;
In my code, m_customName is an AnsiString type variable. TJSONConfig.SetValue procedure requires the key and value both to be of UnicodeString type. The application compiles fine, but I get warnings such
Warning: Implicit strung type conversion from "AnsiString" to "UnicodeString".
Some messages warn saying there is a potential data loss.
Of course I can go and change everything to UnicodeString type but this is too risky. I have't seen any issues so far by ignoring these warnings, but they show up all the time and it might cause issues on a different PC.
How do I fix this?
To avoid the warning do an explicit conversion because this way you tell the compiler that you know what you are doing (I hope...). In case of c.SetValue the expected type is a Unicodestring (UTF16), m_customname should be declared as a string unless there is good reason to do differently (see below), otherwise you may trigger unwanted internal conversions.
A string in Lazarus is UTF8-encoded, by default. Therefore, you can use the function UTF8Decode() for the conversion from UTF8 to Unicode, or UTF8ToUTF16() (unit LazUtf8).
var
c: TJSONConfig;
m_customName: String;
...
c.SetValue('/Systems/CustomName', UTF8Decode(m_customName));
You say above that the key-value pairs are in a file. Then the conversion depends on the encoding of the file. Normally I open the file in a good text editor and find the encoding somewhere - NotePad++, for example, displays the name of the encoding in the right corner of the statusbar. Suppose the encoding is that of codepage 1252 (Latin-1). These are ansistrings, therefore, you can declare the strings read from the file as ansistring. Because UTF8 strings are so common in Lazarus there is no direct conversion from ansistring to Unicode, and you must convert to UTF8 first. In the unit lconvencoding you find many conversion routines between various encodings. Select CP1252toUTF8() to go to UTF8, and then apply UTF8Decode() to finally get Unicode.
var
c: TJSONConfig;
m_customName: ansistring;
...
c.SetValue('/Systems/CustomName', UTF8Decode(CP1252ToUTF8(m_customName)));
The FreePascal compiler 3.0 can handle many of these conversions automatically using strings with predefined encodings. But I think explicit conversions are very clear to see what is happening. And fpc3.0 still emits the warnings which you want to avoid...

Range values extraction in Kendo spreadsheet changes dates to integers

I am using a Kendo spreadsheet to import data from an Excel file so I can plug it into an SQL Server database using Ajax callbacks. The Ajax callbacks work fine, but I have determined that any Date strings are being converted to an integer offset from a base date of 12/30/1899. I have submitted a support ticket to Telerik, but they do not seem to understand the problem.
The data is displayed in the Kendo spreadsheet appropriately as a date. Kendo converts a date input as "12/1/2015" to "12-1-2015".
I am using the latest version of the ASP.NET MVC 5 wrapper, but the JavaScript code is the 2016-1-226-545 version of the JavaScript. The wrapper version seems to be irrelevant, but later versions of the JavaScript have the gulpfile.js, and this conflicts with the Bundleconfig interface on my ASP.NET MVC 5 project, so I simply work with the last version of the JavaScript that works for my setup.
The spreadsheet I am working with is pretty basic to start:
#(
Html.Kendo().Spreadsheet()
.Name("SiteSlotDataSS")
.Rows(10)
.Columns(4).ColumnWidth(100)
.Sheets(sheets =>
{
sheets.Add()
.Name("Study Data");
}
)
)
I use the import option to pull in an Excel spreadsheet and use a simple button with a click event routine to copy the data to a string array to send to the Ajax callback. I have confirmed that the data being sent to the server controller is the same as it is on the client side before being sent. The Date conversion to an integer occurs when the values are extracted from the range.
The code in question that selects the values is:
values = sheet.range("A" + headerRows.toString() + ":" + endRange + (headerRows + rows).toString()).values();
This produces the correct translation of every other column except for columns containing dates.
I tried the following to brute-force the issue, without success:
for (var x = 0; x <= rows; x++) {
sheet.range("K" + (headerRows + x).toString()).format(kendo.spreadsheet.formatting.date);
}
I could try a date function to convert the date back into the original value, but everyone pretty much knows how Telerik's documentation is a bit skimpy and overall simply a nightmare to find answers to questions with.
What is the solution?
It appears that Kendo Spreadsheet stores the date values as an integer offset from 12/30/1899 in days. I determined the "0" value by entering a date of 1/1/1901 to see what came back, then 1/1/1900. The result of the latter was "2", making the base date 12/30/1899. Taking the data and converting it at the server seems to be the best option. I don't really expect much of a response from Telerik.
I have addressed the storage issue with Telerik, and they have acknowledged there is a bug in the spreadsheet widget.
For now, the solution is to bring the values array one row at a time back to the server and do the data conversion server-side. The integer that is returned in the values array for dates is the way the Kendo Spreadsheet stores the information client-side. Formatting the column simply will not do anything but change the client-side display. It will not change how Kendo returns the values matrix from the spreadsheet range selected.
Firstly, I think you mean 12/31/1899. It makes no sense to refer anything to 12/30/1899.
Excel dates start with 1/1/1900, just as do your Kendo (Japanese: "the way of the sword") dates. If you're getting an integer, forcibly coerce it to the corresponding date on the receiving by merely FORMATTING THE COLUMN. There is no need for a specific function to "convert" days-since-1900 counts to text dates (MM/DD/YYYY), as they are the SAME, differing only in human-readable representation.
Of course, it wasn't clear from your description whether Excel was on the input side or the output side of the problem.

Get Windows Long Time Format

I'm trying to get the long time format in Windows (like "hh:mm:ss tt"). I can get the short time format like this:
GetLocaleInfoEx(NULL, LOCALE_STIMEFORMAT, format, 100);
I can't seem to find a constant for LOCALE_LTIMEFORMAT or anything like that. I can get the short time, short date and long date, but how can I query the current user's long time format?
As far as I can tell, windows defines the 'long' time format by LOCALE_STIMEFORMAT (set to something like "hh:mm:ss"), and the short time as LOCALE_SSHORTTIME (which, according to MSDN, is valid for Windows 7 and later).
Does that correspond to your findings, i.e. does it match the user preference in the Region and Language Control Panel item?
For the t specifier, if it is not included into the locale format, then either you are left with always using a custom format (like gbjbaanb said), or perhaps examining the format string for the presence of t or tt, and if absent adding it yourself (though, this might lead to odd results for cultures expecting the tt before the general time, for instance). This should not be necessary though, as the time format used by the locale is responsible for yielding time-strings that make sense (distinguishing between AM and PM, for instance).
What you are looking for is already included in LOCALE_STIMEFORMAT. Sample code:
wchar_t format[80]; // 80 is always enough
int ret = GetLocaleInfoEx(
LOCALE_NAME_USER_DEFAULT,
LOCALE_STIMEFORMAT,
format,
sizeof(format) / sizeof(*format));
if (ret == 0) die(GetLastError());
std::wcout << format << std::endl;
Output on my machine (I live in the USA):
h:mm:ss tt
The "tt" part will be absent for any culture or locale customization that does not display the AM/PM designator.
The LOCALE_STIMEFORMAT is the long time format. To get the short time format you can use LOCALE_SSHORTTIME starting with Windows 7 or cut off the seconds.
To confirm this simply change the long time format in your Control Panel / Region and Language settings.
Try using it with the LOCALE_S1159 and LOCALE_2359 constants which return the text for the AM/PM designators.
I think the issue is that time format is a time format, down to the second. You have to format it yourself if you want AM/PM just like you do with daylight savings time or timezone indicators.

how to internationalize a delphi application [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Translate application
What is the best way to internationalize my application written in delphi xe2 ?
I've seen the stringtable resource but I'm worried because I've got the feeling that the implementation could be time consuming and laborious.
Are there other equally valid methods to do this?
Maybe not the best tool for translations, but I'm using GNU Gettext for many years.
The process is quite simple:
You run dxgettext to extract strings
You translate or give for translation the files
I personally love poEdit tool to translate and manage translation repository
Optional : You merge your translation files into the final EXE
OR you put the translation files in subdirectories and that's it !
http://dxgettext.po.dk/
Update:
1/ GNU Gettext is included in JCL/JVCL library, you just need to activate this option at startup.
2/ Gnu Gettext can translate everything in the library, as VCL, JCL/JVCL also ! It's not just limited to your code !
One option is to use the Integrated Translation Environment in Delphi:
http://docwiki.embarcadero.com/RADStudio/XE3/en/Localizing_Applications_by_Using_Translation_Manager_Overview
Here you can find two articles about this theme:
Multilingua application with GNU gettext
Multilingua application with standard method (IDE)
You can find other methods and commencial components (i have used TsiLang components -excellent library-)
A Greeting.
I don't know is this the best way of internationalize an application, but for me it worked. It's a kind of home made.
I created an xml file, which is the dictionary containing the translations, but you can use any other format, from json, to xls (maybe this is the best). Than implemented a class which read the translations from this file, and a way to register procedures in case of the language is changed runtime, which is I think a good feature.
TDictionary = class
private
fOnChanged: TSignal;
fLanguage: String;
procedure setLanguage( const Value: String );
public
procedure loadFromFile( filename: string );
function getTranslation( id: string; lang: string = '' ): string;
property language: String read fLanguage write setLanguage;
property onChanged: TSignal read fonChanged;
end;
...
function TDictionary.getTranslation( id: string; lang: string = '' ): string;
begin
if lang = '' then
lang := Language; // use the default lang.
// read the translation from the file.
end;
procedure TDictionary.setLanguage( const Value: String );
begin
fLanguage := Value;
onChanged.Execute;
end;
TSignal is a class which register methods, and if you call Execute executes all the registered methods, Maybe in xe2 you have something built in for this, in delphi7 I had to create this class myself, but it's fun to implement.
in a form's createForm:
procedure TMyClass.doTranslate( dictionary: TObject );
begin
with dictionary as TDictionary do
begin
caption := dictionary.getTranslation( 'myclass.caption' );
button.caption := dictionary.getTranslation( 'some id' );
end;
// or you can go through Controls array, and automate the assignment.
end;
procedure TMyClass.FormCreate(Sender: TObject);
begin
Dictionary.onChanged.register( doTranslate );
doTranslate( dictionary );
end;
procedure TMyClass.FormDestroy(Sender: TObject);
begin
Dictionary.onChanged.deregister( doTranslate );
end;
As you can see, this is not a working example what you can copy and paste, I just wanted to show you the idea behind. if something is not clear, comment it, and I can extend my answer.
Some notes:
I think it's important to have the translations in utf8 format.
using xls makes the localizers live easier, and your too, if they ruin your xml file (If the translator is not prof., It can happen that you get back your xml file in microsoft word format)
you can put your dictionary file into resource, and load from there.
Pros
This way you can change the language runtime
if you need another language, you just need to edit the dictionary file.
Cons
If you have many forms, it's a nightmare to connect all the labels, buttons, etc, but you can automate it in smart ways.
It slows down your app a little, but not much, if changing your app language is not happening so often.
There is a product called sisulizer, it works after you have build the executable fies I think. Haven't tried it but I've read a lot about it.
Have a look at this

Resources