April 18, 2008

Unix Time for ASP.NET 3.5 (VB 2008)

I'm a little new to ASP.NET, so maybe I'll figure out later that I didn't need to do this...but I badly miss PHP's date functions. Working with dates in PHP is so easy that I sometimes play with it for fun.

The date object in PHP used Unix Time, which is the number of seconds since midnight GMT on 1 January 1970. Right this second, that number is 1208466537. From what I can tell, ASP.NET does not use this number — the date right now is 04/17/2008 04:09:12 PM. That's alright if you're in a locale that is compatible with that format (i.e., the US), but if you're somewhere else, you've gotta mess around. Furthermore, you have to be cognizant of the time zone. There is no time zone in Unix Time. PHP figures out the local time based on your time zone environment variable. Besides all that, Unix Time is simply an integer, which is easy to store in a database, and easy to manipulate. ASP.NET's date object is ultimately a string, which takes up more space and is harder to work with. (To be fair, ASP's date functions seem quite capable of parsing and manipulating that string.)

I can't do anything the easy way, so I whipped up some code to generate and read Unix Time in VB 2008. First, create the number from the current date and time:

Dim DTDate As Date = DateTime.Now
Dim Epoch As Date = "01/01/1970"
Dim TZone As TimeZone = TimeZone.CurrentTimeZone
Dim TimeZoneOffset As String = TZone.GetUtcOffset(Now).ToString().Substring(0, 3)
Dim TZORaw As Integer = Convert.ToInt32(TimeZoneOffset) * 3600

Dim TZO As Integer

if TZORaw < 0 Then
TZO = 0 - TZORaw
End If

Dim UnixTime As Integer = DateDiff(DateInterval.Second, Epoch, DTDate) + TZO

You wind up with an Integer called UnixTime which will contain your number. I'd much rather store that number in a table. This will work for any time zone that is based on a whole-number hour. Those wacky zones over in India and elsewhere will fail. I also just realized that if your local date format is different than "MM/dd/yyyy" it won't work, so you'd need to change that string. A bit of code is needed to convert it back to a human-readable format:

Dim Today As Date = Epoch.AddSeconds(UnixTime - TZO)
Format(Today.ToSting(), "MM/dd/yyyy hh:mm:ss tt")

This will basically get it back to ASP's "natural" date format. Wonderful.

March 20, 2008

Oracle Calendar with Palm conduit won't sync

Once in a while I'll encounter a PalmOS device that's lost its ability to sync with Oracle Calendar (UMCal). In some cases, the conduits are missing from HotSync. This is how I've fixed it:

Make the sync user an administrator, then log in as that user. Reinstall the UMCal Palm Sync. In my experience, if you don't install it as the sync user (i.e., Run As...), you'll get at least a couple errors which are totally cryptic, undocumented, and misleading.

Now open HotSync, click Applications, and you should see something like this:


For reasons I don't understand, there will be multiple entries for the data types that Oracle uses (two each for calendar, tasks, contacts). You want to use the second name for each of those: Calendar, Tasks, Contacts. Check whichever of those three you need and make sure to uncheck Date Book, To Do List, Address. I also recommend unchecking any of the other unneeded applications further down the list -- it will sync much faster.

Now create a test event in Oracle Calendar and try syncing (initiate the sync from the Palm device). You should see the test event. Repeat for tasks and contacts if necessary.

Finally, don't forget to remove admin rights for the user.

March 19, 2008

Inserting multiple rows in SQL Server and moving data from MySQL

Inserting multiple rows of data in a single SQL statement should be easy. MySQL makes it easy. You simply separate your rows with commas:
INSERT INTO MyTable (FirstName, LastName, BirthYear)
  VALUES ('John', 'Johnson', 1980), ('Pete', 'Peterson', 1981), ('Pradeep', 'Pradeepson', 1982);
Naturally, you can't use this syntax in SQL Server. That'd be too easy! Maybe someday Microsoft will get around to supporting it. For now, you have to do something like this:
INSERT INTO MyTable (FirstName, LastName, BirthYear)
SELECT 'John', 'Johnson', 1980
SELECT 'Pete', Peterson', 1981
SELECT 'Pradeep', 'Pradeepson', 1982
The first version of this query would be especially useful if you're moving from MySQL to SQL Server Express, which doesn't offer any built-in way of importing data (which even Microsoft Access supports). Why would you want to do this? My motto is, "if it ain't broke, break it." Maybe you want to learn SQL Server. So instead, you could try a mysqldump on the table you want to export:
mysqldump -u root -p MyDatabase Names > Names.txt
You'll wind up with a complete catalogue of the structure and contents of the Names table. Assuming the table structure already exists in MSSQL, the only part of the file we're interested in is the INSERT statement, which looks like this:
But as noted earlier, this won't work in MSSQL. Rather than attempting some nasty find-and-replace tactics, I think there's an even better and easier solution: the INTO OUTFILE function. This is used in a SELECT statement and will write the results of the query to a file. We can get very close to the SQL statement that MSSQL needs using this technique. Once again, we'll assume the table structure already exists, and that you've created your auto-incrementing and primary key ID column. In other words, we won't be importing the ID column; MSSQL will create that data for us. Here's the query I developed:
USE MyDatabase;
SELECT FirstName, LastName, BirthYear
FROM MyTable
ORDER BY FirstName, LastName, BirthYear
Save this as a file called DataOutput.sql in MySQL bin directory and execute it like this:
mysql -u root -p < DataOutput.sql
This will write the file where the MySQL's data files are stored. It will return this data:
'John', 'Johnson', '1980'
SELECT 'Pete', 'Peterson', '1981'
SELECT 'Pradeep', 'Pradeepson', '1982'
Not bad! Obviously it isn't exactly what we want, but it would be pretty easy to make the corrections. Just add the INSERT INTO statement, add a SELECT to the first record, and remove the last SELECT. Then execute the query in MSSQL. Easy!

March 6, 2008

Apple application error

This error will appear sometimes when you launch software that has been downloaded: "[Program] is an application which was downloaded from the Internet. Are you sure you want to open it?"


It is caused by extended attributes on the application and it can happen on many programs, including Firefox and Thunderbird. Here's how to fix it:

1. open terminal
2. su to admin
3. cd /Applications
4. xattr -d com.apple.quarantine Thunderbird.app
5. repeat for other applications that have extended attribs

You can check which apps contain these attribs by doing an ls -lsa. You'll see "@" on the far right of the file's permissions listing. Additionally, you can check the attribs on each file by doing a xattr -l [file/dir].