anchor.diff:                         Value
                  end, Values)].
   
  +get_default_timezone(Default) ->
  +    try
  +        riak_core_metadata:get({riak_core, timezone},
  +                               string, [{default, Default}])
  +            of
  +        Value ->
  +            Value
  +    catch
  +        _:_ -> Default
  +    end.
  +
  +timestamp_to_normalized(Str) ->
  +    ProcessOptions =
  +        [
  +         {default_timezone, get_default_timezone("+00")}
  +        ],
  +    Normal = jam:normalize(
  +               jam:compile(
  +                 jam_iso8601:parse(Str), ProcessOptions)
  +              ),
  +    case Normal of
  +        undefined ->
  +            throw(<<"Invalid date/time string">>);
  +        _ ->
  +            Normal
  +    end.
  +
  +to_epoch(Normalized, Exponent) ->
  +    jam:to_epoch(Normalized, Exponent).
  +
   timestamp_to_epoch(Str) ->
       ProcessOptions =
           [
  -         {default_timezone,
  -          riak_core_metadata:get({riak_core, timezone},
  -                                 string, [{default, "+00"}])}
  +         {default_timezone, get_default_timezone("+00")}
           ],
       Datetime = jam:expand(
                    jam:normalize(
  
positive.code: -export([explain_query/1, explain_query/2]).
  -export([explain_query_print/1]).
  
  
  %% NOTE on table_to_bucket/1: Clients will work with table
  %% names. Those names map to a bucket type/bucket name tuple in Riak,
  
negative.code: replace_ast_timestamps(Mod, {Op, Item1, Item2}) when is_tuple(Item1) andalso is_tuple(Item2) ->
      {Op, replace_ast_timestamps(Mod, Item1), replace_ast_timestamps(Mod, Item2)};
  replace_ast_timestamps(Mod, {Op, FieldName, {binary, Value}}) ->
      {Op, FieldName, maybe_convert_to_epoch(catch Mod:get_field_type([FieldName]), Value, Op)};
  replace_ast_timestamps(_Mod, {Op, Item1, Item2}) ->
      {Op, Item1, Item2}.
  
  maybe_convert_to_epoch({'EXIT', _}, Value, _Op) ->
      {binary, Value};
  maybe_convert_to_epoch(timestamp, Value, '>') ->
      %% For strictly greater than, we increment any incomplete
      %% date/time strings by one "unit", where the unit is the least
      %% significant value provided by the user. "2016" becomes
      %% "2017". "2016-07-05T11" becomes "2016-07-05T12".
      Normal = timestamp_to_normalized(Value),
      Epoch = case jam:is_complete(Normal) of
                  true ->
                      to_epoch(Normal, 3);
                  false ->
                      to_epoch(jam:expand(jam:increment(Normal, 1), second), 3)
              end,
      case is_atom(Epoch) of
          true ->
              throw(Epoch);
          false ->
              {integer, Epoch}
      end;
  maybe_convert_to_epoch(timestamp, Value, _Op) ->
      Normal = timestamp_to_normalized(Value),
      Epoch = case jam:is_complete(Normal) of
                  true ->
                      to_epoch(Normal, 3);
                  false ->
                      to_epoch(jam:expand(Normal, second), 3)
              end,
      case is_atom(Epoch) of
          true ->
              throw(Epoch);
          false ->
              {integer, Epoch}
      end;
  maybe_convert_to_epoch(_Type, Value, _Op) ->
      {binary, Value}.
  
  %% I haven't investigated why the values are a nested list
  