A pedant that hangs out in the dark corner-cases of the web.

Wednesday, December 15, 2010

Conspicuous Features Missing From Google Chrome

Things that I miss when I use Google's Chrome browser:

Things that I miss when I use Firefox:

  • speed!

Things that I miss when I use Internet Explorer:

  • not using Internet Explorer

Saturday, December 11, 2010

US Federal Holidays in PowerShell

Here's how to determine whether a date is a US federal holiday using PowerShell.

function Test-USFederalHoliday
{
<#
.Synopsis
Returns the name of the holiday of a date, if it is a U.S. federal holiday.
.Description
The following holidays are checked:
* New Year's Day, January 1 (± 1 day, if observed)
* Martin Luther King, Jr. Day, Third Monday in January
* President's Day, Third Monday in February
* Memorial Day, Last Monday in May
* Independence Day, July 4 (± 1 day, if observed)
* Labor Day, First Monday in September
* Columbus Day, Second Monday in October
* Veteran's Day, November 11 (±1 day, if observed)
* Thanksgiving Day, Fourth Thursday in November
* Christmas Day, December 25 (±1 day, if observed)
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][datetime]$Date,
[Parameter(Mandatory=$false,HelpMessage='Are Saturday holidays observed on Friday?')][switch]$SatToFri,
[Parameter(Mandatory=$false,HelpMessage='Are Sunday holidays observed on Monday?')][switch]$SunToMon
)
$MMdd= '{0:MMdd}' -f $Date
switch($Date.DayOfWeek)
{
'Monday'
{
switch -regex ($MMdd)
{
'^01(?:1[5-9]|2[01])$' {return 'Martin Luther King, Jr. Day'}
'^02(?:1[5-9]|2[01])$' {return 'Presidents Day'}
'^05(?:2[5-9]|3[01])$' {return 'Memorial Day'}
'^090[1-7]$' {return 'Labor Day'}
'^10(?:0[89]|1[01-4])$' {return 'Columbus Day'}
}
if($SunToMon)
{
switch($MMdd)
{
'0102' {return 'New Year''s Day (Observed)'}
'0705' {return 'Independence Day (Observed)'}
'1112' {return 'Veteran''s Day (Observed)'}
'1226' {return 'Christmas Day (Observed)'}
}
}
}
'Thursday'
{
if($MMdd -match '^112[2-8]$') {return 'Thanksgiving Day'}
}
'Friday'
{
if($SatToFri)
{
switch($MMdd)
{
'1231' {return 'New Year''s Day (Observed)'}
'0703' {return 'Independence Day (Observed)'}
'1110' {return 'Veteran''s Day (Observed)'}
'1224' {return 'Christmas Day (Observed)'}
}
}
}
}
switch($MMdd)
{
'0101' {return 'New Year''s Day'}
'0704' {return 'Independence Day'}
'1111' {return 'Veteran''s Day'}
'1225' {return 'Christmas Day'}
}
}

US Federal Holidays in F#

Here's how to determine whether a date is a US federal holiday using F#. You probably want to curry the first two boolean parameters with the appropriate settings (some departments observe Sunday holidays on Monday, and some observe Saturday holidays on Friday).

open System
let getHoliday sunToMon satToFri (date:DateTime) =
match date.Month, date.Day, (date.Day-1)/7+1, date.DayOfWeek with
| 1, 1, _, _ -> "New Year's Day"
| 1, 2, _, DayOfWeek.Monday when sunToMon -> "New Year's Day (observed)"
| 1, _, 3, DayOfWeek.Monday -> "Martin Luther King, Jr. Day"
| 2, _, 3, DayOfWeek.Monday -> "Presidents Day"
| 5, d, _, DayOfWeek.Monday when d >= 25 -> "Memorial Day"
| 7, 3, _, DayOfWeek.Friday when satToFri -> "Independence Day (observed)"
| 7, 4, _, _ -> "Independence Day"
| 7, 5, _, DayOfWeek.Monday when sunToMon -> "Independence Day (observed)"
| 9, _, 1, DayOfWeek.Monday -> "Labor Day"
| 10, _, 2, DayOfWeek.Monday -> "Columbus Day"
| 11, 10, _, DayOfWeek.Friday when satToFri -> "Veterans Day (observed)"
| 11, 11, _, _ -> "Veterans Day"
| 11, 12, _, DayOfWeek.Monday when sunToMon -> "Veterans Day (observed)"
| 11, _, 4, DayOfWeek.Thursday -> "Thanksgiving Day"
| 12, 24, _, DayOfWeek.Friday when satToFri -> "Christmas Day (observed)"
| 12, 25, _, _ -> "Christmas Day"
| 12, 26, _, DayOfWeek.Monday when sunToMon -> "Christmas Day (observed)"
| 12, 31, _, DayOfWeek.Friday when satToFri -> "New Year's Day (observed)"
| _ -> null

You can really see the power of active pattern matching for the Memorial Day case.

Monday, November 22, 2010

No NTFS Compression in .NET?

There is no class in the .NET SDK to use (de)compress files using NTFS! Apparently, people just use interop, which seems like way too much overhead to me.

Sunday, October 31, 2010

Copyfight: Maria Cantwell's response to my concerns

Earlier this year, I sent my concerns about ACTA (and the general scorched-earth approach to copyright that puts the rights of Lady Gaga and the Transformers above consumer protections and even basic human rights) to some politicians. The feedback went something like this:

I'll be as brief as I can:

Personally, I'd like to see us return to a pre-DMCA world where copyright was a civil matter. Sadly, I've scaled back my hopes significantly, and I now just don't want you to destroy freedom to protect a specific business model.

Thank you for your time.

What I got back from Maria Cantwell in July was very disappointing.

Dear Mr. Lalonde,

Thank you for contacting me regarding the Anti-Counterfeiting Trade Agreement (ACTA) negotiations. I appreciate hearing from you on this matter and sincerely regret the delayed response.

As you may know, the ACTA negotiations began in June 2008 with the participation of Australia, Canada, the European Union and its 27 member states, Japan, Mexico, Morcocco, New Zealand, Republic of Korea, Singapore, Switzerland, and the United States. The negotiations, which are scheduled to conclude in 2010, have the goal of providing an international framework to improve enforcement of intellectual property right (IPR) law.

The ACTA initiative aims to create improved, international standards to fight the growing problem of counterfeiting and piracy. The effort is not intended to interfere with the fundamental rights and civil liberties of ordinary citizens, and will be consistent with the WTO Agreement on Trade-Related Aspects of Intellectual Property Rights (TRIPS Agreement) and the Declaration on TRIPS and Public Health.

I am aware of your concerns about the transparency of the ACTA negotiations. However, it is an accepted practice during trade negotiations not to disclose negotiating texts to the public thus enabling officials to engage in the frank exchanges necessary for agreement on complex issues.

You will be pleased to know that the USTR has taken steps to ensure an unprecedented level of transparency in the ACTA negotiations, and won endorsement of the importance of meaningful public input at the second level of negotiations in November 2009. Additionally, on April 21, 2010, the USTR released a public, pre-decisional draft text of the ACTA. It is available for your reference through the USTR website at http://www.ustr.gov/acta.

Thank you again for contacting me to share your thoughts on this matter. You may also be interested in signing up for periodic updates for Washington State residents. If you are interested in subscribing to this update, please visit my website at http://cantwell.senate.gov. Please do not hesitate to contact me in the future if I can be of further assistance.

Sincerely,
Maria Cantwell
United States Senator

I've replied, but don't expect to hear back.

I have to say that I'm am deeply disappointed.

By bringing up public health, it seems clear that you are among those trying to conflate physical counterfeiting with unauthorized digital copying. "Consistency" is also an obvious ploy to slowly ratchet up onerous copyright law by getting excessive laws passed in "sympathetic" regimes then demanding them here.

And far from ensuring unprecedented levels of transparency, it is clear that the USTR is doing everything in his power to keep these negotiations, and the current treaty itself, secret. This is well documented.
http://boingboing.net/2010/02/25/acta-leak-now-we-kno.html

As I rejected it when Vice President Cheney attempted to claim that secrecy was necessary to have "frank discussions" in his energy policy discussions, I reject it here. Anything that can't be said in public is shady when developing policy in a democracy.

The text of ACTA has once again leaked, and once again, it is clear that its supporters (yourself included, apparently) will not rest until all of our Internet traffic is monitored (allegedly for "infringing content"), our laptops and iPods are searched at the border, and entire families are collectively punished (counter to Genevea Convention "consistency") based on specious accusations of media companies.
http://www.boingboing.net/2010/07/14/acta-leaks----again.html

Please tell me you have the integrity to dismiss the made-up losses media companies are constantly parroting, to allow us to create without the constant fear of corporate legal threat, and to protect our right to speak and assemble digitally for the future.
http://www.fsf.org/campaigns/acta/acta-declaration/

Perhaps not surprisingly, Senator Cantwell's second-highest contributor is Microsoft.

Sunday, October 24, 2010

Mini Review: Swype and SlideIt Android sliding keyboards

Sliding keyboards work amazingly well. Given a moderately practiced user typing English text and reasonably fast hardware, I suspect that a "typing" speed could be achieved that would be nearly competitive with a full-sized mechanical keyboard.

Android provides at least two sliding keyboards so far, and here are their relative strengths and weaknesses.

SlideIt

  • Fastest for raw text, though this difference may only be noticeable on lower-end hardware.
  • Supports custom macros, called "shortcuts" that allow for arbitrary letter combinations to expand to any arbitrary text.
  • Does not require swiping over the apostrophe for contractions.
  • Switching to the symbols keyboard then sometimes requires scrolling through rows of symbols, and automatically switches back to the regular keyboard after typing each symbol (which can be frustrating when typing pairs of parentheses or brackets), unless "pinned", which requires an additional keystroke.
  • Symbols and accented letter keys are visible and can be found easily (if not quickly) when scrolling through keyboard.
  • Has built-in voice input support. This is mostly for Android 1.x devices that do not already have this support.
  • Has built-in Graffiti (Palm-style block-letter recognition) support.
  • Limited paged-horizontal display of alternative word matches.
  • Irritatingly disables the shift key after the first letter of a word is typed.
  • More than twenty languages supported.
  • Always includes a return key.
  • Unique keys: ¬ …

Swype

  • Larger keys.
  • Much faster support for capitalization by swiping a letter up above the keyboard, then to the next letter. This makes typing "I" in particular a much faster upward flick than the more cumbersome [Shift], [i].
  • Much faster support for symbols (by long-pressing a letter for common symbols, or switching to the symbols keyboard for a more comprehensive selection).
  • Extended symbols and accented characters are not visible until long-long-pressing a key (in either symbol or regular keyboard mode). Location of symbols can be difficult to find and remember until the mnemonically understood.
  • Numeric keyboard.
  • Limited paged-vertical display of alternative word matches.
  • Contractions require swiping the apostrophe.
  • Swiping period/exclamation/question to space quickly ends a sentence.
  • Variable speed-vs.-accuracy slider setting.
  • Extra hidden keyboard for powerful cursor, selection, and clipboard control.
  • Three languages supported (English, French, Spanish).
  • Return key is often irritatingly replaced with "Done" key.
  • Unique keys: ¿ ¡ „ ð · þ ¶ ª æ œ ß

Wednesday, September 15, 2010

The New Caste System

Welcome to the new caste system. You are either a Creator (noble) or a Consumer (pleb/serf).

Plebs don't get to own anything, like the music, movies, books, or software they buy; they may only license what they purchase. No one without an existing defensive copyright/patent portfolio will be able to become a Creator, since "creation" is only achieved by transforming or combining existing ideas.

Slowly, the scope will creep as you are required to pay a periodic license fee for the architecture you live in, the design of the furniture you use, the clothing and shoes you wear, &c.

Punishment for unauthorized copying/use ("piracy") will just get more draconian, initially as entire households are excommunicated from the Internet for unsubstantiated accusation by the corporate scanbots, but ultimately as "intellectual" "property" (imaginary property) enforcement provides an excuse for capricious, arbitrary, and unlimited affronts to legal rights of protestors and dissidents.

So, anyway, happy Wednesday.

Tuesday, April 06, 2010

Quixotic IE6 Workarounds

Microsoft has renewed support for IE6 until 2014.

If this bothers you, be sure to remember this the next time you are preparing to give Microsoft money!

To celebrate this spineless irresponsibility, here are some coping strategies:

It must be said, however, that if IE6 is a small (single digit percentage) of your web traffic, you probably needn't to spend as much extra time on it as you have in the past. Most things will still work well enough if you build for progressive enhancement/graceful degredation anyway, even though sites may not look quite as beautiful in IE6 without massively increasing your development time to implement various workarounds.

Wednesday, February 24, 2010

Is the end of IE6 finally in sight?

Internet Explorer Contract Addendum - Monday By NoonShould I bother supporting IE6? - Pro Webmasters - Stack ExchangeBrowse SadRIPIE6.comIE6 No MoreBring Down IE 6Explorer DestroyerI Don't Support IE6I dropped Internet Explorer 6StopIEStop Internet ExplorerSaveIE6 ;)Dear IE6IE6ify BookmarkletIE sucksWhy IE SucksEnough IE6Is Internet Explorer 6 Dead?Do I have IE6?IE6 MUST DIEDeath To IE6IE Death MarchHEY-IT - We want to get rid of IE6!Explorer Exposed!IE6 Must Die - Support now! - Twibbon.comPhase Out IE6IE6 UpdateDearIE6 - So LongGOODBYE IE6... I hate you!IE6 Redirection ScriptIE 6 Blocker Script | CSS-TricksIE6 Countdown to DeathToo Cool for Internet ExplorerUpdate Your BrowserBrowser-Update.orgBrowser Upgrade InformationPushuptheweb.comKill Bill's Browser - Switch to FirefoxBrowse HappyIt's Time to Choose A Better BrowserAlternative Browser AllianceCrash IEIEUpdate.nldrop-ie6.dk — Sig farvel til Internet Explorer 6ie6 - aktualizuj już teraz!IE6 FuneralKILL IE 6NoIE6IE6: Do NOT want!The best way to support IE6?Am I using IE6?End 6!StopIE6.comIE6OffendersThe IE6 ListStop Living in the Past! Upgrade IE6

Word on the street is that July 13, 2010 is the official end of life for IE6. Maybe it'll get extended, but Digg has already dropped support, Google Sites and Docs will on March 1, 2010, Google has announced YouTube will drop support March 13, 2010, and Microsoft has been encouraging users to upgrade.

There have been efforts toward, and hopes and predictions of IE6's death in the past, and maybe some (primarily corporate) users may continue to use it anyway. However, Google provides huge momentum, and news coverage, discussion, angry T-shirts, and voodoo dolls are going to make justification of coasting along on IE6 much harder from now on. Norway has been in the fight for a while, there's a petition to pull IE6 from the UK government, and even the hubris of a funeral for IE6.

It just seems like the time is right to spend less time on crazy, quixotic fixes, and invest some time (at least for a while) helping educate or encourage users to make a better browser decision.

Monday, February 01, 2010

Converting between XDocument and XmlDocument, XElement and XmlElement

Here's a class to provide extension methods for conversion between System.Xml and System.Xml.Linq classes:

using System.Xml;
using System.Xml.Linq;

/// <summary>
/// Provides extension methods for simple conversion between System.Xml and System.Xml.Linq classes.
/// </summary>
public static class XmlLinqConversionExtensions
{
  /// <summary>
  /// Converts an XDocument to an XmlDocument.
  /// </summary>
  /// <param name="xdoc">The XDocument to convert.</param>
  /// <returns>The equivalent XmlDocument.</returns>
  public static XmlDocument ToXmlDocument(this XDocument xdoc)
  {
    var xmldoc = new XmlDocument();
    xmldoc.Load(xdoc.CreateReader());
    return xmldoc;
  }
  
  /// <summary>
  /// Converts an XmlDocument to an XDocument.
  /// </summary>
  /// <param name="xmldoc">The XmlDocument to convert.</param>
  /// <returns>The equivalent XDocument.</returns>
  public static XDocument ToXDocument(this XmlDocument xmldoc)
  {
    return XDocument.Load(xmldoc.CreateNavigator().ReadSubtree());
  }
  
  /// <summary>
  /// Converts an XElement to an XmlElement.
  /// </summary>
  /// <param name="xelement">The XElement to convert.</param>
  /// <returns>The equivalent XmlElement.</returns>
  public static XmlElement ToXmlElement(this XElement xelement)
  {
    return new XmlDocument().ReadNode(xelement.CreateReader()) as XmlElement;
  }
  
  /// <summary>
  /// Converts an XmlElement to an XElement.
  /// </summary>
  /// <param name="xmlelement">The XmlElement to convert.</param>
  /// <returns>The equivalent XElement.</returns>
  public static XElement ToXElement(this XmlElement xmlelement)
  {
    return XElement.Load(xmlelement.CreateNavigator().ReadSubtree());
  }
}