Saturday, November 29, 2008

Swatch Internet Time

Back in 1998, a company called Swatch decided to invent a new method of timekeeping. It didn't catch on, but some people embraced it. If you're one of those people, this is for you. We're going to write a function to convert a time value into a Swatch beat. Our PHP programmer friends already have access to this sort of thing through PHP's date() function.


The following code builds upon two other functions previously published here:

IMPORTANT: To return an accurate result, the time value passed in needs to be UTC/GMT (in other words, without offset). There are two ways to achieve this: set your server's time zone to GMT, or use my UTC time function.


ASP

  1. function swatch(someTime)
  2.     swatch = str_pad(floor(((Hour(someTime) * 3600 * 1000) + (Minute(someTime) * 60 * 1000) + (Second(someTime) * 1000)) / 86400), 3, "0", STR_PAD_LEFT)
  3. end function

View ASP implementation on Snipplr

Saturday, November 22, 2008

Mersenne Numbers

Today we're going to write a function to generate Mersenne numbers. This is useful in searching for Mersenne primes.


ASP

  1. function mersenne(x)
  2.     mersenne = 2^x - 1
  3. end function

PHP

  1. function mersenne($x)
  2. {
  3.     return 2^$x - 1;
  4. }

Saturday, November 15, 2008

UTC and Atomic Time

In this special double issue, I'm going to show you how to obtain time values in the GMT timezone, as well as ultra-precise atomic clock time values.


Our PHP programmer friends have a slight advantage against us. Their language is aware of what time zone the server is located in and is capable of doing various things with that information, including returning time values without any timezone offset. ASP has no clue what time zone the server is set for, but we can use XMLHTTP to retrieve a time value from a NIST time server.


ASP

  1. function utcnow()
  2.     dim xmlhttp
  3.     dim response
  4.     ' Server to query datetime from
  5.     Const TimeServer = "http://time.nist.gov:13"
  6.     ' Use XML HTTP object to request web page content
  7.     Set xmlhttp = Server.CreateObject("Microsoft.XMLHTTP")
  8.     xmlhttp.Open "GET", TimeServer, false, "", ""
  9.     xmlhttp.Send
  10.     response = xmlhttp.ResponseText
  11.     set xmlhttp = nothing
  12.     ' Parse UTC date
  13.     utcnow = cDate(mid(response, 11, 2) & "/" & mid(response, 14, 2) & "/" & mid(response, 8, 2) & " " & mid(response, 16, 9))
  14. end function

If you were to compare the value returned by this function and the value returned by the built-in Now() function, you might notice more than just the hour value is different. This could mean you live in one of those funky half-hour-offset timezones, or it could mean that your server's clock is off by a few minutes. If accurate time values are important to you, you need a better Now() function. We can build one on top of the UTCnow() function we just wrote.


ASP

  1. function atomicnow()
  2.     dim utc
  3.     dim offset
  4.     utc = utcnow()
  5.     ' The order of the dates is important here!
  6.     offset = DateDiff("h", utc, now())
  7.     atomicnow = DateAdd("h", offset, utc)
  8. end function

There is expected to be some lag caused by this function, but the order of magnitude should only be milliseconds.


View implementation on Snipplr

Saturday, November 8, 2008

Sinc function

Today we're going to a Sinc function, both normalized and unnormalized. Apparently it's useful in digital signal processing.


ASP

  1. Const M_PI = 3.14159265358979323846
  2. ' Unnormalized sinc function.
  3. function sinc(x)
  4.     sinc = sin(x) / x
  5. end function
  6. ' Normalized sinc function.
  7. ' REQUIRES: constant M_PI
  8. function nsinc(x)
  9.     sinc = sin(M_PI * x) / (M_PI * x)
  10. end function

PHP

  1. // Unnormalized sinc function.
  2. function sinc($x)
  3. {
  4.     return sin($x) / $x;
  5. }
  6. // Normalized sinc function.
  7. function nsinc($x)
  8. {
  9.     return sin(M_PI * $x) / (M_PI * $x);
  10. }

Saturday, November 1, 2008

Nth Day

This week I want to share with you a function that I personally got a lot of use out of. Several years ago I had a situation where there was a calendar with several hundreds recurring events. It was desired to have these events fall on roughly the same day each year. The person responsible for this was spending two or three days at the end of each year planning all the occurrences for the next year on a giant wet-eraseable calendar.


Here's what all the fuss was about: Last year, November 1 was a Thursday. This year, November 1 is a Saturday. Saturday is not a working day for most people, so these events we are scheduling need to fall on week days. Because it fell on a Thursday last year, we'd prefer to have it on a Thursday again this year. This means either pushing it back to October 30 or forward to November 6.


To make the event occur on the same day of the week, we'll store this information in our database and use it to generate the date for a given year. This is called the Nth Day. In the above example, our Nth Day is the first Thursday in November.


ASP

  1. function nthDay(someYear, someMonth, someWeek, someWeekday)
  2.     dim firstDay
  3.     dim someDay
  4.     firstDay = weekday(dateSerial(someYear, someMonth, 1))
  5.     ' Check if the week day of the first day of the month is before or after the given week day.
  6.     if (someWeekday - firstDay) >= 0 then
  7.         someDay = 1 + (someWeekday - firstDay) + ((someWeek - 1) * 7)
  8.     else
  9.         someDay = 1 + (someWeekday - firstDay) + (someWeek * 7)
  10.     end if
  11.     nthDay = dateSerial(someYear, someMonth, someDay)
  12. end function

If developing a system around this concept like I did, it's important to know that some months have a fifth week, depending on how late in the week the first day of the month is. You can't really schedule anything recurring during the fifth week. We kept it open both to give the people conducting the events a little time off, as well as for a place to move an event from the following month in situations where the customer thought it would be too late in the year otherwise.


An idea I had to improve the system, but didn't get around to exploring, was to ignore the months entirely and use the weeks of the year. Nobody wants to schedule anything around Christmas and New Year's anyway, so you don't run into problems around the beginning/end of the year like you do at the beginning/end of a month. Under this system, first Thursday of November becomes Thursday of Week 44. Scheduling a recurring event this way is not only easier, but also more consistent from year to year.


View ASP implementation on Snipplr