loving perl one-liners

I’ve always been a big perl fan.

Just ran into another case, where I dusted off some old dusty synapses and did a little perl oneliner.

Given a pile of text files, prepend each line of each file with a ‘* ‘ (to make it handy for a markdown list.

find . -name '*.txt' -print0 | xargs -0 perl -pi -e '$_ = "* $_"' 

done and done.

A file like this

line 1
line 2
line 3

now looks like this

* line 1
* line 2
* line 3

And it hit every text file (*.txt) in this directory and below.

If you haven’t played with perl oneliners (or ruby oneliners for that matter) check out these resources:

How I learned to love ActiveSupport::TimeZone

I recently wrote up a basic calendaring system. Naively, I figured that I could set the time zone for the application in Rails.config, and everything would magically work out. No such luck. Here’s what I learned:

  • Time.now uses the server time.
  • DateTime.parse and Time.strptime use the server time.

Put this together, and you’ve got fun times.
When users enter date information (as they do when entering calendar entries, for example), they will typically enter a string with no time zone.

06/24/2002 12:30pm

for example. What time is that? What time zone? DateTime.parse and Time.strptime will both give you server time. Here’s where ActiveSupport::TimeZone comes in to play.

  • Time.zone.now is smarter. It uses Application.config.time_zone.
  • Time.zone.parse parses the time, also, using Application.config.time_zone.

For the application at hand, we know that all events entered should be in one time zone. We can set the time zone for the app to that time zone.

# in config/application.rb
...
module MyAppName
  class Application < Rails::Application
    ...
    config.time_zone = "Pacific Time (US & Canada)"
  
    ...
  end
end

For all cases where want the current time (to initialize a date input box, for example), we use Time.zone.now. This is equivalent to

Time.now.in_time_zone(MyAppName::Application.config.time_zone)

Finally, when we get input time/date from client forms, we use Time.zone.parse like so:

class DateInputController

  def create
     start_time = Time.zone.parse(params[:start_time])
     end_time = Time.zone.parse(params[:end_time])
     ...
  end
end

This guarantees that the start/end time will also be interpreted in the application’s time zone. If, in this case, you had decided to use strptime, you’d end up with times that were in the server time zone.

Try it for yourself. In my application’s Rails console I did:

irb> Time.zone.now
=> Wed, 30 Jan 2013 08:23:26 PST -08:00
irb> Time.now
=> 2013-01-30 16:23:26 +0000
irb> Time.zone.parse('2010-01-12')
=> Tue, 12 Jan 2010 00:00:00 PST -08:00
irb> DateTime.parse('2013-01-12')
=> Sat, 12 Jan 2013 00:00:00 +0000
irb> DateTime.strptime('2013-01-12','%Y-%m-%d')
=> 2013-01-12 00:00:00 +0000

I ran these lines on a server that was living in UTC time zone. You’ll notice that Time.now and Time.zone.now have the same time, but are set to different zones. The PST is the offset from our application’s time zone (in config/application.rb). Here we also can see (highlighted lines) that Time.zone.parse does the right thing – uses the application’s time zone, where as DateTime.parse does not. Both DateTime.parse and DateTime.strptime don’t know what to do about time zone, so they set it to 0-offset (UTC).

My last bit of advice that helped me find the places I’d missed was to put my development machine in another time zone; one that is not UTC and not the application’s time zone. When I did that, I was able to identify (and write solid tests), around cases where I had not dealt properly with conversions of client < = > server times.

Futher Reading: