Determine Daylight Savings status for different time zone in Powershell - powershell

Is there a slick way in PowerShell to ascertain if a past date in another time zone is Daylight Savings or not? Here is the situation, our database is in Europe and the times and dates are local to that server. Since Europe and America start and stop DST at different times, i need to take into account the hour difference for those times.
Thanks for your advice.

There is no need to try to determine whether DST is in effect or not. Just let the .NET Framework do the conversion for you.
First, decide which time zone IDs you are converting from and to.
You said your input time was in Europe, but you didn't specify exactly where. Like the US, Europe has multiple time zones. I'll assume you meant CET/CEST (UTC+1/+2). In Windows, you can use any of the following identifiers for this:
"Central Europe Standard Time"
"Central European Standard Time"
"Romance Standard Time" (why? who knows.)
"W. Europe Standard Time" (don't get fooled by the name, it's still central)
These are all the same (in Windows) except for their display names. If you want to be precise in which one you pick, refer to the CLDR reference.
For the US Central time zone, use "Central Standard Time".
Then just use the TimeZoneInfo.ConvertTimeBySystemTimeZoneId function, as follows:
# collect your input (through db, or whatever mechanism you have)
$inputDateTime = Get-Date -Date "2017-06-27 00:00:00"
# pick your time zones
$fromTimeZone = "Central Europe Standard Time" # EU
$toTimeZone = "Central Standard Time" # USA
# convert
$outputDateTime = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(
$inputDateTime, $fromTimeZone, $toTimeZone)
# output
Write-Output $outputDateTime

I know this is an older thread, but I actually needed to be able to determine whether or not it's DST currently. We have a server whose local TZ is set to UTC (which doesn't see DST) and have an automation that needs to be able to know when it's 4pm local time. So the script is all in UTC, but I can then add an hour or not based on the value of the result of this beast:
$DST = ([System.TimeZoneInfo]::ConvertTimeFromUtc(
(get-date).ToString(),
[System.TimeZoneInfo]::FindSystemTimeZoneById("Central Standard Time")
)).isdaylightsavingtime()

Cole, I love the inspiration as your response was a needle in a haystick and just what I needed. However, it produced an error. After some messing around, I got the following to work:
$isDST = ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById("Central Standard Time"))).IsDaylightSavingTime()
(in PowerShell v4)

Related

Converting timestamps in Perl

I am looking to convert timestamps such as the following
2019-01-01T02:15:00+00:00
Into Australian Eastern Standard Time in Perl.
I have over 10,000 of these timestamps, any help would be really appreciated
I need to input them into a mysql DB with a format of YYYY-MM-DD hh:mm:ss
You would use the standard Perl module Time::Piece. It provides the standard strptime and strftime functions. The first allows you to parse a timestamp with a template and the second outputs a timestamp based on the same kind of template. To change timezones you would add or subtract the number of seconds difference.
$t = Time::Piece->strptime("2020-11-04T01:46:00", "%Y-%m-%dT%H:%M:%S");
$t += $offset;
print $t->strftime("%Y-%m-%dT%H:%M:%S");
Or if your current time is the current locale and you're always converting from GMT:
$t = Time::Piece->strptime("2020-11-04T01:46:00", "%Y-%m-%dT%H:%M:%S");
$l = localtime $t->epoch;
print $l->strftime("%Y-%m-%dT%H:%M:%S");
Now if you need to do something more complicated than that (daylight savings time, leap seconds), there is the DateTime module but it is correspondingly far more complicated to use.
See also How can I parse dates and convert time zones in Perl?
HTH

Powershell: Get the current time with w32tm

My task is to get the current time with the w32time service from a Windows 2016 Server, and compare it to the time showed on this server. What I find online about this service is synchronising, and doing more complicated stuff, but I simply need the "official" time in the simplest form, so I can compare the two, and check if there is more than a few seconds of difference between the two.
I can get some useful info with
w32tm /stripchart /computer:time.windows.com /samples:1 /dataonly
Which output has the line
09:59:38, +00.1323527s
Is this the difference between the NTP server and my server? Is there a more straightforward way to achieve what I intend to do, or should I just crop this line out the output, and use it?
According to this the +00.1323527 value you see is the actual offset between local time and the target computer time. If you’re seeing differences in the 0.00* range for actual offset, you can be highly confident that you have the correct system time. Anything with less than a second offset is reasonably good as well.
You can strip the time difference out like:
$currentTime, $timeDifference = (& w32tm /stripchart /computer:time.windows.com /samples:1 /dataonly)[-1].Trim("s") -split ',\s*'
$timeDifference
# or if you rather have a numeric value than a string, cast it to Double:
[double]$timeDifference

Error parsing time-zone with Time::Piece

Executing a simple Perl script
use Time::Piece;
my $t = Time::Piece->strptime('08:00 PM AST', "%I:%M %p %Z");
I got the following error: Error parsing time at /usr/local/lib/perl5/Time/Piece.pm line 469.
Is this a bug in the library or there is something wrong with the above code? When I remove AST time-zone from the input string, it works, but when time-zone is left, it fails.
I don't know what exact time-zone will be in input string, so I cannot adjust that part on my end. AST (see Wikipedia) is a proper abbreviation for Atlantic Time Zone, so it should work. But it does not!
The time zone field is ambiguous and cannot be parsed. For instance, CST is the abbreviation for China Standard Time, Central Standard Time, and Cuba Standard Time.
The module documentation says that the strptime method is from FreeBSD, where the %Z format accepts either the local time zone or GMT and nothing else. This may be true of strptime, but I can confirm only that, where I am located, GMT is acceptable while UTC and AST are not.
The solution I would recommend is to preprocess your time strings, replacing the time zone abbreviation with an unambiguous time zone offset. For instance AST (assuming you meant Atlantic Standard Time and not Arabia Standard Time) would be replaced with -0400, since it is four hours behind UTC. Then you can parse it with a %z format specifier and get the correct result.
use Date::Parse;
my $t = str2time('08:00 PM AST');

How can I change the timezone of Log4perl timestamps

My web server is in a timezone different from mine and I am using this pattern layout in the Log4perl config:
log4perl.appender.LOGFILE.layout=PatternLayout
log4perl.appender.LOGFILE.layout.ConversionPattern=%d | %p | %l | %c | %m%n
The %d produces a date/time in the timezone of the server. How can I make it log the date/time in my local timezone instead?
I am aware that the following:
$Log::Log4perl::DateFormat::GMTIME = 1;
Causes date/time to be logged in GMT however I could find nothing in the documentation to support arbitrary timezones.
If you set the time zone for Perl in general, that will fix the logs, too. Might be too blunt an instrument for your purposes:
use POSIX qw(tzset);
$ENV{TZ} = 'desired time zone goes here';
tzset;
To go even blunter, if you have access, you can set TZ in the environment of the web server itself and have everything in the desired zone.
But I think you're better off logging everything in UTC.

Determining Local Time in another Timezone

How can I determine the current date and time of various countries using a PERL script that executes on a server in the US? For example, getDTnow() should determine the current date and time on the server and use that to return the date and time of various countries.
P.S: It would be great if this can be done using only the built-in functions, without any external modules.
Conclusion: Date maths is [use swear word here] complicated and easy to get wrong. Other perl gurus on IRC, groups and other parts of the net confirmed what Ether had been advicing me - use DateTime. DVK's solution is also pretty neat for those of you who don't mind messing with the perl environment. (Note: Though on windows, the caveats section of the Time::Piece docs says one should be careful while 'Setting $ENV{TZ} in Threads on Win32').
DateTime is a wonderful library that can use standard timezones to do everything you desire and more:
use DateTime;
# returns local time in Italy
my $dt = DateTime->now(time_zone => 'Europe/Rome');
# prints time in desired format
print "The current date and time in Italy is: ", $dt->strftime('%Y-%m-%d %T');
You can control which timezone localtime returns in via TZ environmental variable:
local $ENV{TZ} = ":/usr/share/lib/zoneinfo/Asia/Tokyo";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime();
print "$sec,$min,$hour,$mday,$mon,$year,$wday,$yday\n"'
# Prints 40,58,4,12,0,111,3,11
local $ENV{TZ} = ":/usr/share/lib/zoneinfo/Europe/London";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime();
print "$sec,$min,$hour,$mday,$mon,$year,$wday,$yday\n"'
# Prints 41,58,19,11,0,111,2,10
Unfortunately, the path above is different on different Unixes (/usr/share/lib/zoneinfo on Solaris, /usr/share/zoneinfo on Linux). Since there appear to be no other variations, a slightly portable version would check which of the 2 directories exists and use that - but this obviously only works on Solaris and Linux and may be other unixes. No idea about Windows/MacOS/whatnot.
Valid locations for TZ can be found here: http://www.timezoneconverter.com/cgi-bin/tzref.tzc (but not all of them would necessarily be available on your system - check the above directory).
Please see http://en.wikipedia.org/wiki/Tz_database for more info on TZ database.
You could always store the variation from your timezone in a hash where the key is the timezone and the value is the adjustment from the current time. then when you pass the current time it should return the local time for that zone.