Amsterdam DO’s and DON’Ts – revised 2019 edition

Back in 2012, I wrote a post with travel advice for Amsterdam. We just got back from another trip there, and I thought I’d revise my advice – most of it still applies, but there have been a few changes. So here’s my 2019 Amsterdam DO’s and DON’Ts. Come back in 2026 for another revision!

Amsterdam Dos and Don’ts – 2019 revised edition

We recently spent a week in Amsterdam before and after taking a river cruise through the Netherlands and Belgium; I might eventually post photos from the trip, but in the meantime, I wanted to share some possibly-useful tips for others travelling to Amsterdam and environs.

Money

  • DO tell your credit/debit card companies that you will be using your card in the Netherlands and when you’ll be there.
  • DO get money from ATMs rather than buying it before you leave the US; there are ATMs at the airport and all over town and you’ll get a much better rate. (2019 note: Use bank ATMs if at all possible to get the best exchange rate and lowest fees; avoid Travelex and the like.)
  • DO expect to find some shops which only accept cards and will not accept cash. (2019 note: I saw quite a few shops which were card-only, and a few which were cash-only. I ran into a couple of shops which would not accept Visa or Mastercard credit cards but would accept debit cards.)
  • DON’T get the Travelex “Cash Passport” Chip and PIN card – the exchange rate is hideous and they demand your Social Security number.
  • DO expect to be able to use your US credit card when you are dealing with people – even though the Dutch all have Chip and PIN cards, every credit card machine I saw in a shop could also accept a US magstripe card. (2019 note: Of course, all the machines accepted US chip cards, too; sometimes the shop wanted a signature, but often they didn’t.)
  • (New for 2019) DO expect to use your US credit card to be able to buy train tickets and transport cards from automated machines.
  • DON’T take the option of paying in US Dollars using your credit card. The rate is probably not as good as your card company will give, and if your card has a surcharge for international transactions, you’ll have to pay that surcharge even if the transaction is in US Dollars.
  • DO carry a few Euros in change with you at all times for small purchases and toilets – many public toilets charge between 20–50 cents for access.

Getting into town from the airport

  • DO take the train unless you’re staying far from the city center.
  • 2019 advice: DO expect to be able to use your US credit card at the machines at the train station to buy your ticket.
  • DO buy your train ticket in advance from Belgian Rail; print it at home and bring it with you.
  • DO buy Second Class tickets for this trip unless you have a lot of luggage or can’t manage four steps up or down stairs.
  • DO know that the trains to Centraal Station leave from Schiphol platforms 1 and 2.
  • DON’T get on a “FYRA” train at Schiphol – it will cost you! You want to get on an “IC” train. The trains are marked on the sides of the cars; both use the same platforms.

Getting around town

  • DO walk if you can – the touristy part of Amsterdam is small, and everything of interest is within a 45-minute walk (mostly less). Take public transport only when you’re in a hurry.
  • DO watch out for bicycles and motorbikes, especially when crossing a bike path (and every street has bike paths). Treat them as you would any other fast-moving dangerous vehicle.
  • DON’T be surprised by motorbikes (or bicycles) on the sidewalk, either, though they are usually going slowly there.
  • (2019 changes) DON’T plan on using cash to buy a ticket on a tram, train, or bus. Either buy your ticket (or pass) in advance or use your card to make the purchase.

iAmsterdam card

  • DO buy the iAmsterdam card.
  • DON’T buy it at the VVV office at Centraal Station – there are long lines. 2019 advice: Buy it at the iAmsterdam shop at Centraal Station (on the IJ side of the station); you can even use your US credit card to buy it from their vending machine!
  • DON’T pre-purchase the card over the Internet, which means picking up the card in person at the VVV office – in that same long line, of course.
  • DO be strategic about the time of day that you activate the pass. It is valid for 24/48/72 hours, not 1/2/3 days. If you activate a 24-hour pass at 11am on Wednesday, you can use it all the rest of that day and then enter a museum before 11am on Thursday and stay there the whole day. This works best for major museums, like the Maritime Museum or the Van Gogh, of course. If you’re really hardcore, you could go to the Maritime Museum at 10am on the last day of your pass and get a ticket, immediately go to another nearby museum and see it, then return to the Maritime Museum because your ticket is good for the entire day.
  • DO realize that the museum pass and the travel pass are completely separate after you buy them; you need not activate them at the same time (or even on the same day).
  • DO realize that the discount offers in the booklet are valid even after your card expires (I think they go to the end of the year); you just need to bring the card and the booklet.
  • DON’T plan to go to the Anne Frank House on the iAmsterdam card. 2019: You have to buy your tickets online in advance (they go on sale exactly 2 months in advance).
  • 2019: DO get your timeslots for the van Gogh Museum as soon as you have your iAmsterdam card numbers.

Sex, drugs, and rock ‘n’ roll

  • DON’T be afraid of walking through the Red Light District (of course, be aware of your surroundings, just as you would anywhere else).
  • DON’T take photos of “red rooms” or the women working in them.
  • DON’T go to a coffeeshop for coffee.

Eating and drinking

  • DO expect the inside of restaurants to be non-smoking (both kinds of smoke).
  • DO expect a lot of [tobacco] smokers just outside of a restaurant.
  • DON’T expect free refills on coffee.
  • DO expect free tap water but you have to ask for it.
  • DO expect service charges to be included in your bill; round up to the next Euro or two if you’re especially pleased. I ran into one restaurant where service was marked as “Not Included” on the bill and tipped about 10% – I have no idea if that was right or not.

Staying connected

  • DO arrange for an international package from your cell carrier (if it’s not already included, as it is with T-Mobile or Google Fi). DON’T use your phone if you don’t have a package – the prices are ridiculous.
  • DO consider getting a local SIM if you want to use a LOT of data.
  • DO look for “Free Wi-Fi” hotspots; many small restaurants offer free Wi-Fi. One near our hotel gave us the password when we stopped to look at their menu and told us the service was available 24/7. We wound up having breakfast there four times!
  • DO look for free Wi-Fi from free-hotspot.com if you’re near a fast-food chain like McDonalds, Burger King, or Subway.

    Language

  • DON’T expect to need to know much (if any) Dutch. All tourist-oriented businesses are completely English-friendly, and almost everyone in the Netherlands seems to speak and understand English.
  • DO try to sound-out written Dutch if you need to figure out a sign; it looks unlike English, but I found it fairly easy.
  • DO say “Dank U Well” (“thank you”).

TIL I learned how (and how NOT) to restore my Mac backup

They say you never know if you have a real backup until you try to use it. They’re right.

TL;DR

  • Don’t encrypt your drive until you’ve restored your data
  • Don’t exclude things from Time Machine backup

The details

I sent my 2017 MacBook Pro to Apple because the keyboard was acting up. And as long as I was at the Genius Bar, I thought it’d be a good time to mention a weird problem I’d had when using Screen Mirroring on my Apple TV (moving the cursor would reveal things lower in z-order – it was weird); the Genius duly wrote that down and sent my machine to the depot for repair.

A few days later, the machine was back in my hands; not only had they replaced the keyboard and the top case (as I’d expected), but they also had replaced a few other parts – and they’d either wiped or replaced the SSD, so I had a virgin installation of Mac OS and none of my data. I booted up the machine, and, for security, told it to turn on FileVault to encrypt the SSD; then I set about restoring my data.

Plan A

I had multiple backups: Time Machine, a bootable clone drive (made with SuperDuper!), and Backblaze for offsite backup. I thought that the easiest solution would be to reboot from the clone drive and restore to the SSD, so I did exactly that.

The restore went fine, except for one small problem – SuperDuper! was unable to update the PreBoot environment. When I tried to boot from the SSD, I got a blinking folder with a question mark, which meant that the system couldn’t find the startup disk. I booted from the clone again and used System Preferences to set the startup disk to the SSD; this time, instead of the question mark, I was asked for a disk password…which, of course, I didn’t have.

Back to the clone, where I could easily mount the SSD and see its contents. Searching gave me this thread, but I couldn’t figure out how to apply the hints to my environment, so it was time for Plan B.

Plan B

I booted the “Install High Sierra” USB stick I’d kept around from last year and erased the SSD. Then I restored from my Time Machine backup. Many hours later, I was able to boot the SSD, and all seemed well.

Except…my desktop background was wrong. And my Dropbox folder was empty (though that was easy to fix by firing up Dropbox). And when I looked further, I realized that I didn’t have any of my photos, nor my iTunes library, nor my DevonThink databases. It was as if they’d never existed. But they were on the clone drive. Hmmm….

Plan C

I booted the clone and fired up SuperDuper! again. And, again, I restored the SSD from the clone, using “Smart Copy”, which found 150GB already on the SSD, and about 200GB of data that needed to be copied.

This time, when I booted the SSD, all was well – I had all of my data.

I opened Time Machine Preferences and discovered that I’d excluded my iTunes library, my Pictures folder, and my DevonThink databases from being backed up in order to save space on the drive in the Time Capsule that I was sharing among several computers. Oops. Especially since I’d stopped sharing a Time Capsule months ago and was backing up to a directly-attached 4TB drive, with plenty of space.

Conclusion

All seems to be well; I’ve removed the exclusions from Time Machine and it’s busily backing up everything now.

I haven’t checked to see if the Apple TV screen mirroring problem has been fixed – I guess I should find out, though.

I think I’ll wait a few days after Mojave ships before I upgrade; I really don’t want to go through this again any time soon!

TIL how to build Python 3.7 with statically-linked libssl and libcrypto

I use a Virtual Private Server on DreamHost to run the Toastmasters District 101 website. For the most part, I’m happy with their service, and with a shell prompt, it’s usually easy to install whatever software I need.

Except Python 3.7. Python 3.7 requires a newer level of OpenSSL than DreamHost offers, and since I don’t have root access on a VPS, I can’t just replace OpenSSL. Compiling a current version and installing it in a directory ($HOME/usr/local) was easy enough:

./config --prefix=$HOME/usr/local --openssldir=$HOME/usr/local/openssl   
make   
make test   
make install   

Building Python 3.7 was also easy, but getting it to use my copy of OpenSSL was not.

At first, I tried adding my OpenSSL to LD_LIBRARY_PATH, which worked, but it made git complain: no version information available (required by ssh), and that seemed unfortunate (and made me worry that I might break other things).

After much searching, I found Python issue 21541, which had the hints I needed to statically-link my copy of OpenSSL into the Python executable.

First, run configure:

./configure --prefix=$HOME/opt/python-3.7.0 --with-openssl=$HOME/usr/local/

Then uncomment and change the section of Modules/Setup dealing with SSL to this:

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
SSL=$HOME/usr/local
_ssl _ssl.c \
    DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
    L$(SSL)/lib -Wl,-Bsymbolic $(SSL)/lib/libssl.a $(SSL)/lib/libcrypto.a

After that, the usual make && make install worked.

I’ve moved!

Ducklings on the move with mama duckI’ve moved this blog to Linode. It should run a little faster, cost me a little less, and let me do more things with the server.

I took the photo near my house a couple of days ago while I was out for a walk; I was surprised to see a mama duck and her flock of ducklings going the other way!

In Praise of Venice Classic Radio

We like to have light classical music in the background while we’re at home. During most of the year, we usually listen to our local classical station, KDFC, or one of SiriusXM‘s classical channels. But once Thanksgiving rolls around, things change. “Holiday” music begins to creep into the playlist, and as the month goes on, it takes up more and more airtime.

But I’ve found an alternative – Venice Classic Radio. Their playlist is blessedly free from “holiday” music for most of the month – they do play the occasional real classical Christmas piece, but it’s a small part of their programming, and they mostly save it until Christmas Eve and Christmas Day. I heard Silent Night yesterday and Nutcracker today, both of which were very pleasant indeed; they also played Kol Nidre today, much to my surprise.

Check them out any time you want classical music without interruption (they play a 30-second multi-lingual station ID at the top of the hour, but that’s the only announcement you’ll hear) – and especially during December!

Happy Holidays to all, and to all a good night!

TIL why you “lay down” Port

When Jeff was four or five, I thought it would be a nice idea to buy a bottle of Port from his birth year and share it with him on his 21st birthday. I found a bottle of “Late Bottled” Vintage Port at Trader Joe’s (this was before we started going to wineries!) and put it aside.

Jeff’s 21st birthday came – but he was away at college. The bottle sat.

Years passed.

Jeff’s home for the holidays, and I thought New Year’s Eve would be a good time to finally share the Port. I took the bottle out of the closet and tried to open it.

The cork had disintegrated. I managed to get enough of the cork out of the bottle to pour the Port through a strainer and into our glasses – but it was undrinkable.

If only I’d read the back side of the bottle and followed their advice.

back label

Next time for sure!

TIL not to plug an Amazon Echo Dot into my Mac Mini

I recently put an Amazon Echo Dot in my home office. It needs USB power; rather than plug in yet-another-power-adapter, I plugged it into a spare port on a USB hub connected to my Mac Mini.

All was well…until I needed to reboot the Mac. Then I noticed two things:

  • A normal reboot took a long time to show the login screen (more than a minute, versus the usual 10 seconds)
  • Pressing Option during the reboot (to try to reboot from another device) failed – the machine hung, never giving me the screen with devices to try.

I tried resetting NVRAM and the SMC; no dice.

Eventually, I managed to reboot and took a look at the system log; there were many, many error messages like this:

Oct  6 12:52:00 office kernel[0]: 000573.331885 AppleUSB20HubPort@14233000: AppleUSBHostPort::disconnect: persistent enumeration failures

I started disconnecting devices, and when I unplugged the Dot, the messages stopped appearing.

I’m now powering the Dot with its own power supply, plugged into a power strip. It works great, and the Mac Mini is happy, too.

TIL about Python’s “enumerate”

I’ve been writing Python for more than 10 years, and I can’t count the number of times I’ve written code like this:

index = 0
for thing in array:
    do_something_with(index, thing) # Because I care about the index AND the item
    index += 1

But today I learned about the built-in enumerate function which does exactly the same thing, but avoids any chance of getting “index” and “thing” out of sync (not that I’ve ever made that mistake, of course…).

I’m not going to rewrite any old code for fear of adding new bugs, but I’ll remember to enumerate going forward.

Thanks, Dr. Drang!

Adding email addresses to Divi’s “person” module for District 101

The Divi theme is powerful, but it has some quirks. One of those is in the “person” module, which doesn’t provide a place for contact information (phone and email). I wanted to add email for the people listed on the District Leadership Team page; the obvious way was to add the email address to the text for each person, but that felt inelegant.

A quick Google search led me to a free plugin, Person Module Extended by Dani Dwiputra, made available through Divi Space. I installed the plugin, added emails in the appropriate fields, and could have called it a day, except that I wanted to make some changes to the presentation.

Here are the diffs to get the results I wanted:

++ Desktop/person-full-social/dd-person-modules.php 2016-07-24 21:12:21.000000000 -0700
@@ -465,2 +465,12 @@

+        if ( '' !== $member_email ) {
+            $contact = sprintf('<a href="mailto:%1$s" class="et_pb_member_email">%1$s</a>', esc_html( $member_email ) );
+            $contact .= ( '' !== $member_phone ? sprintf(' | <a href="tel://%1$s" class="et_pb_member_phone">%1$s</a>', esc_html( $member_phone ) ) : '' );
+        } else {
+            $contact = ( '' !== $member_phone ? sprintf('<a href="tel://%1$s" class="et_pb_member_phone">%1$s</a>', esc_html( $member_phone ) ) : '' );
+        }
+        if ( '' !== $contact ) {
+            $contact = '<p>' . $contact . '</p>';
+        }
+
        $output = sprintf(
@@ -471,4 +481,4 @@
                    %8$s
+                   %7$s
                    %1$s
-                   <p>%7$s  |  %6$s</p>
                    %9$s
@@ -483,3 +493,3 @@
            ( '' !== $member_phone ? sprintf( '<a href="tel://%1$s" class="et_pb_member_phone">   %1$s</a>', esc_html( $member_phone ) ) : '' ),
-           ( '' !== $member_email ? sprintf( '<a href="mailto:%1$s" class="et_pb_member_email">   %1$s</a>', esc_html( $member_email ) ) : '' ),
+           $contact,
            ( '' !== $position ? sprintf( '<p class="et_pb_member_position">%1$s</p>', esc_html( $position ) ) : '' ),
@@ -493,2 +503,2 @@
 }
-new DD_Builder_Module_Team_Member;
\ No newline at end of file
+new DD_Builder_Module_Team_Member;
diff -r -U1 Downloads/person-full-social/module-extend.php Desktop/person-full-social/module-extend.php
--- Downloads/person-full-social/module-extend.php  2016-07-20 10:58:09.000000000 -0700
+++ Desktop/person-full-social/module-extend.php    2016-07-24 21:15:17.000000000 -0700
@@ -9,2 +9,3 @@
  * License: GPL2
+ * Modified by David Singer
  */

Thanks, Dani!

Speeding up “Feed Them Social” for District 101

The District 101 Toastmasters website uses the Feed Them Social plugin to add our Facebook and Twitter feeds to our homepage.

It works well, but it can be slow – if it needed to go to Facebook to update its data, it could take as much as 10 seconds to build the page; even if data was in the plugin’s cache, it took a couple of seconds to build the HTML. You can see the shortcodes I had on the home page below.

I thought about writing my own program to mine the Facebook Graph and the Twitter Feed. It would let me produce exactly what I needed, but it would be a perpetual maintenance headache (and I don’t plan to be Webmaster forever). I needed a better answer.

And then it struck me – if I could figure out a way to use the plugin as part of a batch process and save the HTML, I could get the plugin’s processing time out of the critical path, and I wouldn’t have to keep up with changes to the Facebook and Twitter APIs. Here’s what I did:

  • Created a special version of the home page, with the calls to the plugin in the proper place in the page layout (just in case it mattered), but with none of the other features of the home page.
  • Surrounded the calls to the plugin on the special page with flag lines so I could easily pull out the HTML generated by the plugin, using a simple Python program.
  • Made the special page password-protected in WordPress to keep it out of the visible menu structure shown to site visitors.
  • Wrote a script to be called periodically by cron that:
    • used curl to fetch the special page
    • ran the Python program to extract the HTML from Feed Them Social
    • saved the result as a file
  • Replaced the calls to the plugin on the homepage with a couple of lines of PHP to include the saved file as part of the homepage

The result: the homepage loads at least 3.5 seconds faster and looks the same.

Here’s the relevant part of the special page (the calls to FTS are the same as those I used to have on the homepage).

Start Flag
[fts_facebook id=d101tm posts_displayed=page_only type=page]
[fts_twitter twitter_name=d101tm]
End Flag

Here’s the shell script:

# Update the cached static file for social media from Feed Them Social
mydir=$PWD
secret=password for the WordPress page
cd ~/files/social
# The next operation will take a while, so we write to a temporary file
outfile=newfts$$.html
curl -sL "http://d101tm.org/wp-login.php?action=postpass" -d "post_password=$secret" -e "http://d101tm.org/path to the special page/" -b /dev/null | $mydir/updatefts.py > $outfile
# If all went well, we can replace the real file
if [ -n $outfile ]; then
    mv $outfile fts.html
else
    echo $outfile is zero length!
    exit 1
fi

And here’s the Python program:

#!/usr/bin/env python
""" Extract the HTML generated by Feed Them Social from stdin, write to stdout"""

import sys
startflag = 'Something unlikely to appear on the page'
endflag = 'Something else unlikely to appear on the page'
havestart = False
haveend = False

def findendflag(s):
    """ Returns a tuple: (any data before the endflag,
                          whether the endflag was found) """
    if endflag in s:
        return (s.split(endflag,1)[0], True)
    else:
        return (s, False)

for l in sys.stdin.readlines():
    if not havestart:
        res = l.split(startflag,1)
        if len(res) > 1:
            havestart = True
            (l, haveend) = findendflag(res[1])
            sys.stdout.write(l)
    elif not haveend:
        (l, haveend) = findendflag(l)
        sys.stdout.write(l)