+1  A: 
SELECT
    m.amount
FROM
    measurement m,
    to_date('Dec 01 1900', 'Mon DD YYYY') AS A(d1),
    to_date('Feb 28 1900', 'Mon DD YYYY') AS B(d2),
    to_date('Feb 28 1901', 'Mon DD YYYY') AS C(d3)
WHERE m.taken
    BETWEEN
        d1 AND
        CASE WHEN d2 < d1 THEN d3 ELSE d2 END

References: conditional expressions, data type formatting functions.

EDIT: Sorry, I thought you wanted a specific year:

SELECT
    amount
FROM
    (SELECT
        M.amount, M.taken,
        to_date('Dec 01 ' || extract(YEAR FROM M.taken), 'Mon DD YYYY'),
        to_date('Feb 28 ' || extract(YEAR FROM M.taken), 'Mon DD YYYY')
     FROM
        measurement AS M
     ) AS A(amount, taken, d1, d2)
WHERE
    (d2 >= d1 AND taken BETWEEN d1 AND d2)
    OR
    (d2 < d1 AND (taken <= d2 OR taken >= d1));

If the set is big, this doesn't have a lot of chances for optimization. In that case, you can have an SQL function that converts all the dates to a certain year (say taken - (extract(year from taken) - 1900) * '1 year'::interval) and then compare with Dec 02 1900 and Feb 28 1900. That way you can index the result of this date conversion function AND you don't have to calculate two dates for each entry.

Artefacto
This will only return the values for the single iteration. How do you make it return values for all years? And thank you, this is a much more elegant solution than checking date differences.
Dave Jarvis
For example, `to_date('Dec 01 '||extract(YEAR FROM m.taken), 'Mon DD YYYY') AS A(d1)` does not work because the FROM cannot refer to other relations of the same query level.
Dave Jarvis
@Dave Jarvis I think I got it now.
Artefacto
@Artefacto: Looking good; will run a few more tests. I had just started to write a loop to generate the appropriate conditional between statements.
Dave Jarvis
@Dave Jarvis I added a performance remark.
Artefacto
@Artefacto: Works nearly perfectly. It has a problem with leap days (when you select Feb 29), but it is not important enough to fix. (Leap days become March 1st, which is fine.) I also changed the last line to use <= d2 and >= d1.
Dave Jarvis
@Artefacto: The weather station data is usually 365 measurements per year, for an average of 24 years, per station. Most queries don't span more than a few hundred stations. The data is indexed and clustered by station (then date) so I'm hoping there will not be a performance hit.
Dave Jarvis
@Artefacto: And thanks again!
Dave Jarvis
FYI: You don't need to call to_date(). PostgreSQL recognizes a wide range of date formats automatically, as long the year-month-day ordering is obvious (i.e. month names) or at least consistent with your DATESTYLE setting. For example, you should be able to use this syntax instead: date ('Dec 01 ' || extract(YEAR FROM M.taken)). The "date" here is not a function but a SQL-standard indicator that the next expression should be interpreted as a date, not its normal data type (although you need the parentheses as the type cast would have precedence over the concatenation).
Matthew Wood
@Matthew: Thanks! That shaves about 15 ms off the query. ;-) Moreover, though, it makes the query easier to read.
Dave Jarvis