Hey, Scripting Guy! Question

Hey, Scripting Guy! I really enjoyed the 2007 Winter Scripting Games, but one thing I noticed is that you listed the deadlines for all the events using Redmond time. I understand that you can’t list deadlines using the local time for every time zone in the world; however, maybe you could show us how to write a script that could convert Redmond time to our local time. Any chance of you doing that for the 2008 Winter Scripting Games?

-- OD

SpacerHey, Scripting Guy! AnswerScript Center

Hey, OD. Considering the fact that it’s been just about a year since you sent this email you might have thought, “I bet the Scripting Guys forgot all about the time zone issue with the Scripting Games.” Well, rest assured, OD, that the Scripting Guys rarely, if ever, forget anything. That doesn’t mean that we’re actually going to follow up on something; heavens no. But we won’t forget about it.

And even if we did, the Scripting Editor would no doubt swoop down on her broomstick and offer a … gentle … reminder.

She’s very good at that.

So no, we didn’t forget about this question; instead, we’ve been sitting on it until the time was ripe for answering it. And now that the Scripting Games are just two days away (the “opening ceremonies” are scheduled for Friday, February 15th), well, the time is about as ripe as it’s ever going to be.

So can we show you a script that canconvert Redmond time to your local time? You know what? Not only can we show you a script like that, we will show you a script like that. In fact, here it is right now:

strComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")For Each objTime in colTime    intBias = objTime.BiasNextdtmRedmondTime = #2/19/2008 3:00 PM#dtmGreenwichTime = DateAdd("n", 480, dtmRedmondTime)dtmLocalDeadline = DateAdd("n",intBias, dtmGreenwichTime)Wscript.Echo dtmLocalDeadline

You know, you’re right: this would have been a good event in the Scripting Games, wouldn’t it? That’s because it isn’t particularly hard, but it is a little bit tricky. And that’s typically the type of event we like to include in the Scripting Games.

Oh, well. Maybe next year.

For now, though, let’s see if we can explain how this baby works. As you can see, we kick things off by connecting to the WMI service on the local computer. Could we run this script against a remote computer? Sure, although if that remote computer is in the same time zone as your local machine there isn’t much point in running the script against a remote computer. But if you do want to run the script against a remote machine (perhaps to help a long-distance friend convert Redmond time to their local time) simply assign the name of the remote computer to the variable strComputer, like so:

strComputer = "atl-ws-001"

After connecting to the WMI service we then use the following line of code to retrieve a collection of all the time zones that a computer belongs to:

Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")

Note that, in the universe we live in, a computer can belong to only a single time zone; thus this query is going to return only a single item. Could there be a parallel universe in which the accepted laws of physics don’t apply and computers could belong to more than one time zone at the same time? Hey, don’t ask us; we’re just Scripting Guys.

Incidentally, the fact that Win32_TimeZone returns only a single item makes this class a “singleton” class. And yes, that would have been a good question to pose during the Scripting Games, too. Dang; if we’re not careful, today’s column is going to be way better and way more challenging than the actual Scripting Games!

Which would mark the first time this column was better than anything.

After we issue our query we next set up a For Each loop to loop through each item in the collection. And yes, we know: because Win32_TimeZone is a singleton class it has only one item in it. Nevertheless, a collection is a collection, and we still have to use a For Each loop to walk through it, regardless of the number of items in that collection.

Note. Or at least that’s the way it used to be, in this universe. However, in Windows Vista it’s possible to directly access an item in a collection without using a For Each loop. For more information, see our Script Center article WMI Indexer.

Inside this For Each loop we do just one thing; we grab the value of the Bias property and store it in a variable named intBias:

intBias = objTime.Bias

What’s the Bias property? Well, the Bias property tells us the difference (in minutes) between local time and Universal Time Coordinate time. That’s the official SDK explanation; in more practical terms, the Bias property tells us the difference (in minutes) between local time and Greenwich Mean Time. For example, when it’s 10:00 AM in London (home of the Prime Meridian) it’s 2:00 AM in Redmond. Redmond time is 8 hours earlier than Greenwich Mean Time, meaning the Pacific Standard Time time zone has a Bias of -480 minutes.

But why do we even need to know the Bias for the local time zone? We’ll explain that in just a minute.

Before we get to that, however, we need to create a date-time value representing the date and time in Redmond. For example, if the deadline for a particular event (say, Event 1 in the Sudden Death Challenge) is February 19, 2008 at 3:00 PM we can create a date-time value for that deadline using this line of code:

dtmRedmondTime = #2/19/2008 3:00 PM#

Note. Why the pound signs (#) surrounding our date-time value? That helps ensure that VBScript treats the value as a date and not as a string.

That brings us to this line of code:

dtmGreenwichTime = DateAdd("n", 480, dtmRedmondTime)

What are we doing here? Well, here we’re using the DateAdd function to add 480 minutes to the date-time value we just created. (When working with the DateAdd function, the “n” parameter represents minutes. Don’t use “m” to add minutes; the “m” parameter would end up adding 480 months, not 480 minutes.) Why are we adding 480 minutes to our Redmond date-time value? Well, as we noted earlier, Redmond time is 8 hours earlier than Greenwich Mean Time. To convert Redmond time to Greenwich Mean Time we need to add 8 hours (480 minutes).

But why do we even want to convert Redmond time to Greenwich Mean Time? Well, directly converting a time from one time zone to another can be a little tricky; that’s due, in part, to the fact that some time zones have a negative bias (like -480) and others have a positive value (like 120). Rather than mess around with all this we decided to perform this operation using two steps: we convert Redmond time to its equivalent time in Greenwich Mean Time; then convert the Greenwich time to our local time. Granted, it’s an extra step, but it’s also a little easier to code. And much easier for people to visualize.

As you might expect, then, our next step is to convert the Greenwich time to the local time. That’s what this line of code does:

dtmLocalDeadline = DateAdd("n",intBias, dtmGreenwichTime)

This time we’re adding (or subtracting, if we have a negative bias) minutes to Greenwich time. How many minutes are we adding? To tell you the truth, we don’t know; we’re relying on the variable intBias to take care of that for us.

See how this all works? We start out with the following Redmond time value:

2/19/2008 3:00 PM

When we convert this value to Greenwich Mean Time we get this value:

2/19/2008 11:00 PM

We then use our local time zone bias to convert Greenwich time to local time. For example, suppose we live in Athens, Greece. Athens is two hours ahead of Greenwich Mean Time; that means it has a bias of 120 minutes. If we add 120 minutes to our Greenwich time we get this:

2/20/2008 1:00 AM

In other words, when it’s 3:00 PM Monday in Redmond it’s 1:00 AM Tuesday in Athens. That’s how you can convert one of our Pacific Standard Time deadlines to a local time deadline. And you can do this regardless of your location.

At least in this universe.

By the way, if you ever need to know the current time in Redmond you can use this script:

strComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")For Each objTime in colTime    intBias = objTime.Bias    intBias = intBias * -1NextdtmLocalTime = NowdtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)dtmRedmondTime = DateAdd("n", -480, dtmGreenwichTime)Wscript.Echo dtmRedmondTime

What, exactly, does this script do? Well, it first uses the Now function to grab the current date and time; it then employs this line of code, and time zone bias, to convert the current date and time to Greenwich Mean Time:

dtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)

Note that, in our For Each loop, we multiplied intBias by minus 1. Why? Because we’re no longer going from Greenwich time to local time like we did in our first script; instead, we’re going from local time to Greenwich time. Because we’ve reversed direction we need to reverse the sign, turning a bias like 120 minutes to -120 minutes.

Finally, we add -480 minutes to Greenwich Mean Time to determine the time in Redmond:

dtmRedmondTime = DateAdd("n",-480, dtmGreenwichTime)

If it’s 7:43 AM on February 20th in Athens we should get back the following value for Redmond time:

2/19/2008 9:43 PM

Pretty cool, huh?

By the way, if that all seems a little too complicated, well, there is an alternative: you can simply take a look at this page, where we’ve taken the deadline times (8:00 AM for the main Scripting Games events; 3:00 PM for the Sudden Death Challenge events) and converted them to local times for various cities and time zones throughout the world.

And yes, it would have been way easier to simply point people to this Web page rather than write a couple scripts (and an entire column). But you know what they say: when all you have is a hammer everything looks like a nail. And when you’re a Scripting Guy – well, everything looks like a nail to us, too. But since we don’t have a hammer, we don’t have much choice except to write scripts instead.

Speaking of scripts, are you literally counting the minutes until the Scripting Games begin? Well, relax, and stop counting. Assuming that the Games officially open at 8:00 AM PST on February 15, 2008, you can use the following script to tell you how many minutes are left until the Games begin:

strComputer = "."Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")For Each objTime in colTime    intBias = objTime.Bias    intBias = intBias * -1NextdtmLocalTime = NowdtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)dtmRedmondTime = DateAdd("n", -480, dtmGreenwichTime)dtmOpeningDay = #2/15/2008 8:00 AM#Wscript.Echo DateDiff("n", dtmRedmondTime, dtmOpeningDay)

We’ll see everyone on Friday, February 15th. What time on Friday? Well, that you should now be able to figure out for yourself.

Or you can just look at this Web page. Good luck in the Games, everyone!