Why does PowerShell always use US culture when casting to DateTime? - date

When trying to read a CSV yesterday, I noticed that PowerShell seems to always assume US date format when using [datetime]"date".
My regional settings are all correct, and [DateTime]::Parse("date") uses the UK date format (dd/mm/yyyy).
Is this a bug, or a deliberate decision? If a deliberate decision, is this documented anywhere?
PS D:\> [DateTime]"12/10/2012"
10 December 2012 00:00:00
PS D:\> [DateTime]::Parse("12/10/2012")
12 October 2012 00:00:00
(Note: on a US machine, I expect these objects will be the same, but not so here on my machines in the UK).
Note: I don't want to change the format (it's a file from an external source), I don't want to format dates in output, I know I can use [DateTime]::Parse(). The question is the bit that ends with a ? :-)

It is a deliberate decision. When casting a string to a DateTime you can use either the braindead US format or ISO 8601 – [datetime]'2012-10-12' works just fine and is much nicer to read.
The reason that this is limited and restricted is that scripts should not have a dependency on the current culture, at least for literals and quasi-literals (like casted strings). This is a major problem in writing robust batch files and you certainly don't want the same problems in PowerShell.
Lee Holmes has an explanation, which could be considered semi-official, as he is/was on the PowerShell team at MS:
To prevent subtle internationalization issues from popping into your scripts, PowerShell treats [DateTime] '11/26/2007' (a date constant) like a language feature – just as it does [Double] 10.5 (a numeric constant.) Not all cultures use the decimal point as the fractions separator, but programming languages standardize on it. Not all cultures use the en-US DateTime format, resulting in millions of internationalization bugs when people don’t consider the impact of having their software run in those cultures.
What Lee forgets to mention is what I wrote before, that the much more sensible ISO 8601 format works as well.
No documentation of this exists in either the PowerShell documentation or the Language Specification (v2), sadly. However, there is very little evidence that points to this being a bug.

You can force the culture for a single command if needed:
PS C:\> [System.Threading.Thread]::CurrentThread.CurrentUICulture = "en-US" ; [System.Threading.Thread]::CurrentThread.CurrentCulture = "en-US"; [DateTime]::Parse("12/10/2012")
Monday, December 10, 2012 12:00:00 AM
PS C:\> [System.Threading.Thread]::CurrentThread.CurrentUICulture = "en-GB" ; [System.Threading.Thread]::CurrentThread.CurrentCulture = "en-GB"; [DateTime]::Parse("12/10/2012")
12 October 2012 00:00:00

Related

Is there a simpler way to work with UK date format in Powershell?

To work with UK date format, as is my preference, the following code snippet will get me a UK date format (Powershell does not take into account machine locale).
$UKdate = [datetime]::Parse($req.ServicePoint.Certificate.GetExpirationDateString(),([Globalization.CultureInfo]::CreateSpecificCulture('en-GB')))
This seems unwieldy, particularly when the language is normally so concise. Is there a better way that I'm not aware of?
PowerShell does take the locale into account, but casting to [DateTime] does not.
That is, if you were to run this with a UK culture it'll parse it as a UK date:
Get-Date $req.ServicePoint.Certificate.GetExpirationDateString()
Where as this will always choose en-US:
[DateTime]$req.ServicePoint.Certificate.GetExpirationDateString()
Chris

In an ISO 8601 date, is the T character mandatory?

I'm wondering if the following date is ISO8601 compliant :
2012-03-02 14:57:05.456+0500
(for sure, 2012-03-02T14:57:05.456+0500 is compliant, but not that much human readable !)
IOW, is the T between date and time mandatory ?
It's required unless the "partners in information interchange" agree to omit it.
Quoting an earlier version of the ISO 8601 standard, section 4.3.2:
The character [T] shall be used as time designator to indicate the
start of the representation of the time of day component in these
expressions. [...]
NOTE By mutual agreement of the partners in information interchange,
the character [T] may be omitted in applications where there is no
risk of confusing a date and time of day representation with others
defined in this International Standard.
Omitting it is fairly common, but leaving it in is advisable if the representation is meant to be machine-readable and you don't have a clear agreement that you can omit it.
But according to Wikipedia:
In ISO 8601:2004 it was permitted to omit the "T" character by mutual agreement as in "200704051430", but this provision was removed in ISO 8601-1:2019. Separating date and time parts with other characters such as space is not allowed in ISO 8601, but allowed in its profile RFC 3339.
UPDATE : Mark Amery's comment makes a good point, that permission to omit the [T] does not necessarily imply permission to replace it with a space. So this:
2012-03-02T14:57:05.456+0500
is clearly compliant, and this:
2012-03-0214:57:05.456+0500
was permitted by earlier versions of the standard if the partners agreed to omit the T, but this:
2012-03-02 14:57:05.456+0500
apparently is not (though it's much more readable than the version with the T simply omitted).
Personally, if ISO 8601 compliance were required, I'd include the T, and if it weren't then I'd use a space (or a hyphen if it's going to be part of a file name).
See also RFC 3339 section 5.6, mentioned in Charles Burns's answer.
That date is not ISO-8601 compliant as Keith Thompson indicated, but it is compliant with RFC 3339, a profile of ISO 8601.
Sort of. See NOTE at the bottom of the following text from RFC 3339:
date-time = full-date "T" full-time
NOTE: Per [ABNF] and ISO8601, the "T" and "Z" characters in this
syntax may alternatively be lower case "t" or "z" respectively.
This date/time format may be used in some environments or contexts
that distinguish between the upper- and lower-case letters 'A'-'Z'
and 'a'-'z' (e.g. XML). Specifications that use this format in
such environments MAY further limit the date/time syntax so that
the letters 'T' and 'Z' used in the date/time syntax must always
be upper case. Applications that generate this format SHOULD use
upper case letters.
NOTE: ISO 8601 defines date and time separated by "T".
Applications using this syntax may choose, for the sake of
readability, to specify a full-date and full-time separated by
(say) a space character.

Bug in Zend_Date (back in time)

I have a very strange problem, Zend_Date is converting my timestamp to a year earlier.
In my action:
// Timestamp
$intTime = 1293922800;
// Zend_Date object
$objZendDate = new Zend_Date($intTime);
// Get date
echo date('Y-m-d',$intTime).'<br>';
echo $objZendDate->get('YYYY-MM-dd');
This outputs:
2011-01-02
2010-01-02
Can anyone tell me what i'm doing wrong?
From the ZF issue tracker it seems this is a known issue:
Recently a lot of ZF users are filing a bug that Zend_Date returns the wrong year, 2009 instead of 2008. This is however expected behaviour, and NOT A BUG!
From the FAQ:
When using own formats in your code you could come to a situation where you get for example 29.12.2009, but you expected to get 29.12.2008.
There is one year difference: 2009 instead of 2008. You should use the lower cased year constant. See this example:
$date->toString('dd.MM.yyyy');
instead of
$date->toString('dd.MM.YYYY');
From the manual
Note that the default ISO format differs from PHP's format which can be irritating if you have not used in previous. Especially the format specifiers for Year and Minute are often not used in the intended way.
For year there are two specifiers available which are often mistaken. The Y specifier for the ISO year and the y specifier for the real year. The difference is small but significant. Y calculates the ISO year, which is often used for calendar formats. See for example the 31. December 2007. The real year is 2007, but it is the first day of the first week in the week 1 of the year 2008. So, if you are using 'dd.MM.yyyy' you will get '31.December.2007' but if you use 'dd.MM.YYYY' you will get '31.December.2008'. As you see this is no bug but a expected behaviour depending on the used specifiers.
For minute the difference is not so big. ISO uses the specifier m for the minute, unlike PHP which uses i. So if you are getting no minute in your format check if you have used the right specifier.
To add to zwip's answer, what happens behind the scenes is that your date format YYYY-MM-dd is actually translated into o\-m\-d, which is then passed to PHP's date() function internally with the timestamp you provided.
Like mentioned in the other answer, and in the documentation for the o format on the date format page, the calculation of the year based on the ISO week can sometimes result in the year being one different to the value that you expect.

Which Perl module can handle a variety of date formats containing unicode characters?

My requirement is parsing xml files which contains wide varieties of timestamps based on the locales at which they are written. They may contain Unicode characters in case of Chinese or Korean locales. I have to parse these timestamps and put then in a standard format something like 2009-11-26 12:40:54 to put them in a oracle database. Sometimes I may not even know the locale and yet I have to parse the timestamps.
I am looking for a module that automatically detects the timestamp format (including unicode characters for am and pm in their local language) and converts in to epoch time so that I can convert it back to what ever way I like to.
I have gone through similar questions in this forum. Few suggested DateFormat module, and Date::Parse module. The perl distribution I am using is 5.10 so Date::Manip doesn't come as a core module. As I am supposed to use just the basic core modules and few CPAN modules(on request I cannot ask for all),
I request you to kindly suggest me a good module that suffices all my requirements.
Thanks in advance
DateTime::Locale should do what you want.
You might have a look at Date::Manip. Don't know if it supports the languages you need but there is some UTF8 support in it. In any case once you get the dates extracted it has a UnixDate method to easily output in whatever format you want. Also resolves time zones.

Why does my Falcon script print the date a month ahead instead of today's date?

Today is April 25, 2009 which in US format is abbreviated month-day-year, so today is 04-25-09. This line
> CurrentTime().toString("%m-%d-%y")
should print "04-25-09". Instead it prints "05-25-09". Why is that? According to the docs CurrentTime() returns a TimeStamp instance. TimeStamp has a toString() method which accepts a date/time format as a parameter, which is supposed to be in
strftime format. Is there something wrong with my understanding of the code? I am using Falcon 0.8.14.2("Vulture") on Windows Vista (64-bit)
2: http://linux.die.net/man/3/strftime strftime format
I also posted this question on the Falcon Google Group. Apparently, this is an issue with Falcon itself and is fixed in version 0.9.1. Version 0.9.1 will be officially released in a week or two according to the response I received from Giancarlo Niccolai, the inventor of the Falcon programming language.