Jon Skeet may need to correct me, as I'm assuming this is correct in nodatime:
// Timezone data provider (inject with DI)
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
// London Timezone (can keep this as a singleton, since it'll be used often)
var londonTimeZone = timeZoneProvider["Europe/London"];
// Get your date/time from the database and map it as being local to London timezone
var yourDateFromDb = new DateTime(2013, 01, 23, 21, 00, 00); // This is what you'll get back from your database (although you may get back a DateTimeOffset)
ZoneLocalMapping zonedDbDateTime = londonTimeZone.AtLeniently(LocalDateTime.FromDateTime(yourDateFromDb)); <-- This is your date time with the correct offset (taking into account DST etc.)
// Map the London zoned date/time to the users local date/time
var usersTimezoneId = "Europe/Paris"; // <-- Store this value in users profile/db
var usersTimezone = timeZoneProvider[usersTimezoneId];
var usersZonedDateTime = zonedDbDateTime.WithZone(usersTimezone);
Assert.That(usersZonedDateTime.Hour == 22);
You should probably be aware that during timezone transitions (autumn clock change), you may get 2 possible dates for the zonedDbDateTime. The code here just gets the first or earliest date/time.
Edit: Updated code snippet with changes suggested by Jon Skeet