String to datetime conversion error in Powershell v5 - powershell

I have a problem with 2 lines of code, which don't work as I expect. The point is that the DateTime object is being converted to string and back to DateTime, using default conversion, without explicit format specification.
$timeString = [DateTime]::Now.ToString() # contains 17.01.2017 20:01:30
$time = [DateTime]$timeString # PS blows with error
So, basically, it uses the default date format to format the string, but then it seem to use some other format to parse it back. The following line of code will work, however:
$otherTime = [DateTime]"01/17/2017 20:01:30" # will get the initial date
Could someone point me to proper documentation on the matter of types conversion, and why in this case it would use different formats to convert data back and forth?
Thanks in advance.

Parsing dates is always a nightmare. Especially if you live in the tiny part of the world that is called 'outside US' :)
In general formatting and parsing dates in .NET (and many other things as string comparison) are controlled by culture settings. In some cases then default behavior is to use the current culture settings. Convert.ToDateTime is one of them. If you take a look into the documentation (Convert.ToDateTime Method (String)) it says:
If value is not null, the return value is the result of invoking the
DateTime.Parse method on value using the formatting information in a
DateTimeFormatInfo object that is initialized for the current culture.
The value argument must contain the representation of a date and time
in one of the formats described in the DateTimeFormatInfo topic.
That's why it converts from your localized date string. In other cases the default behavior is to use the 'Invariant Culture' setting which usually means 'US settings'. Most of the methods are overloaded and can take a parameter that specifies the culture that should use, but it requires a little search into the .NET documentation.
As a rule of thumb: Don't use strings that are localized if they are not going to be shown to the end user. Always try to find the 'Invariant Culture' variant of the method, and use it for formatting and parsing of the strings. It will save you from many headaches.

You're implicitly calling Convert.ToDateTime(String), but this method's valid formats are hardcoded (and don't appear to be listed). From your output date format, I see that you're likely not in the US, which is probably what most of the formats are centered towards.
Instead, you can explicitly use Convert.ToDateTime(String, IFormatProvider) to tell it which culture format provider you want.
[Convert]::ToDateTime($timeString, [System.Globalization.DateTimeFormatInfo]::CurrentInfo)
I'm on a US system, so I'm not entirely certain if this will work yet.
You can also use [DateTime]::TryParse() or [DateTime]::TryParseExact() to explicitly specify the format(s) you want.

Related

Benefits of running toISOString() on a server log date object

I've been looking into Koa.js recently as a next-gen option for running a server (looks good so far...) and came across the following code in an API example:
function *reqlogger(next){
console.log('%s - %s %s',new Date().toISOString(), this.req.method, this.req.url);
yield next;
}
Most of this code looks pretty good, but I'm not sure whether to leave toISOString() in. The first console.log parameter(s) is formatting the result as string(s) anyway, so why would I want to bother converting the string to ISO format?
Are there any additional benefits I might see down the line to declaring like this? Are there particular functions that prefer date objects in ISO format, for example, or is it just a matter of personal preference?

How do I call WriteObject() of Cmdlet class to output objects with different types?

Right now I'm calling WriteObject(identities1, enumerateCollection:true) first and then WriteObject(identities2, enumerateCollection:true).
If identities1 and identities2 are the same type, the output looks okay. But if they are different types, the output for identities2 is blank.
What did I do wrong here?
This is quirk of how the PowerShell formatting (F&O) engine works. I've argued (apparently unsuccessfully) that this is a bug. You should find that the output is there if you use Format-List. Where I've seen this problem is that the first set of objects uses table formatting (either configured by a format ps1xml file or has <= 4 properties). Then the different object type has > 4 properties. PowerShell can't format the objects in tabular format so it just punts completely. I haven't tried this, but if you create a format ps1xml1 file for your output types, you could try to force both types to use list formatting.

Strict date pattern for DateTextField in Wicket

I have a DateTextField component in my application and I want the input of date using a predefined pattern. The pattern that I need is "yyyy-MM-dd". I created the DateTextField using the following code.
DateTextField dtf_ExpiryDate = DateTextField.forDatePattern("ExpDate", "yyyy-MM-dd");
dtf_ExpiryDate.add(new DatePicker());
It helps to prevent date input in most of other formats. But it accepts input in dd-MM-yyyy format and converts it into some weird format. For example, 12-06-2013 is automatically converted to 0012-06-20.
Is there a way to throw an error when the date is given in dd-MM-yyyy ?
Javadocs of DateTextField says that the conversion is done internally using the Joda time parser. Is there a way to add more constraints ?
I really don't want the data to be captured as String and add a StringValidator to check if it confirms to the pattern using Regex.
Thank you
As far as I know, the answer is NO. DateTextField uses DatePattern or DateStyles internally and it is not possible to enforce stricter rules. If you don't want to use Javascript (custom) or JQuery, you have to use a REGEX to validate the input.
Have a look at here. Use the StrictPatternDateConverter class shown below to enforce a strict validation for the input.
Yep! StringRegExp is a good solution. But another solution could be the use of jqWicket. It provides a MaskedInputBehavior. Take a look at: http://code.google.com/p/jqwicket/wiki/MaskedInputExample

Do I need to provide an IFormatProvider when converting a date to a string with a specific format?

If I'm using this:
DateTime.Now.Date.ToString("yyyy-MM-dd")
FXCop complains that I'm violating CA1305 and says that I should provider an IFormatProvider. Do I need to? I'm asking for the date in a specific format anyway (which is the format I'm expected to put it into the XML as).
Would providing a format provider make any difference? Might it actually produce the wrong results in this case?
Why don't you want to specify the format provider?
If it is just laziness then I can recommend defining two snippets. ic for CultureInfo.InvariantCulture and cc for CultureInfo.CurrentCulture.
Never assume anything about how conversion to string works with the default culture. Not everyone in the world uses the gregorian calendar. Some day you customer might hire a contractor with a computer with another calendar as default and then you are not generating correct XML. Explain then to your customer that you didn't want to follow the FxCop recommendation.
Best thing would be if .Net included a Xml Culture. Then you could just do
DateTime.Today.ToString("d", CultureInfo.Xml)
For some reason Microsoft choose to create a separate class instead XmlConvert. The class has been there since .Net 1.0.
XmlConvert.ToString(DateTime.Today, "yyyy-MM-dd")
will always create a correct Xml date.
Not sure if it is bug or intended behaviour but XmlConvert.ToString(DateTime.Today, "d") will not create a valid Xml date.
so after a bit more research it seems that in my instance it doesn't make any difference, but in the general case months might be displayed in a specific locale.
More details here:
http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx

Zend framework currency validation

How can I validate (a form element in this case) to ensure that the value is a currency?
Have looked at Zend_Validate_Float.
Needs to check that value is between 0 and 2dp.
Ideally locale-aware (as ZVF is) to allow for locale specific formatting (thousands, decimal as comma/dot)
Would also want to extend to allow/disallow negative values
And provide optional upper/lower limits.
Is the key, as I can do 3. and 4. with a chain.
Do I need regex?
AFAIK there is no validator for currency in ZF yet.
You need to write a custom one. See docs for writing custom validators.
Basically, the simplest thing you can do is to normalize input to floating point number (+ currency symbol if you need locale). But correcting user input is not a good solution.
For locale specific formatting you will probably need locale data stored in Zend_Locale_Data. But for comparing input values you will have to write custom currency converter.
Detecting used locale is not so simple, so I'd suggest creating additional select field, for choosing pre-defined format (e.g. locale) and using this value for your custom validator attached to the currency field.