Skip to content
Browse files

COUCHDB-627 - Support all timezones

Some timezones are incorrectly handled by OTP's calendar module. The
ironic thing is that we only ever need the time in GMT (for HTTP
response headers and the log file).

This patch duplicates httpd_util:rfc1123_date/0 and /1 but uses
universal time everywhere, avoiding the broken conversion code.

Also relates to COUCHDB-1513, a duplicate of COUCHDB-627.
  • Loading branch information...
1 parent f5341a7 commit b1a049bb7091d3d75092b68bb3645ae909653547 @rnewson rnewson committed Aug 15, 2012
View
4 src/couch_replicator/src/couch_replicator.erl
@@ -553,7 +553,7 @@ init_state(Rep) ->
committed_seq = StartSeq,
source_log = SourceLog,
target_log = TargetLog,
- rep_starttime = httpd_util:rfc1123_date(),
+ rep_starttime = couch_util:rfc1123_date(),
src_starttime = get_value(<<"instance_start_time">>, SourceInfo),
tgt_starttime = get_value(<<"instance_start_time">>, TargetInfo),
session_id = couch_uuids:random(),
@@ -706,7 +706,7 @@ do_checkpoint(State) ->
?LOG_INFO("recording a checkpoint for `~s` -> `~s` at source update_seq ~p",
[SourceName, TargetName, NewSeq]),
StartTime = ?l2b(ReplicationStartTime),
- EndTime = ?l2b(httpd_util:rfc1123_date()),
+ EndTime = ?l2b(couch_util:rfc1123_date()),
NewHistoryEntry = {[
{<<"session_id">>, SessionId},
{<<"start_time">>, StartTime},
View
6 src/couchdb/couch_httpd_misc_handlers.erl
@@ -44,12 +44,12 @@ handle_welcome_req(Req, _) ->
send_method_not_allowed(Req, "GET,HEAD").
handle_favicon_req(#httpd{method='GET'}=Req, DocumentRoot) ->
- {{Year,Month,Day},Time} = erlang:localtime(),
+ {{Year,Month,Day},Time} = erlang:universatime(),
OneYearFromNow = {{Year+1,Month,Day},Time},
CachingHeaders = [
%favicon should expire a year from now
{"Cache-Control", "public, max-age=31536000"},
- {"Expires", httpd_util:rfc1123_date(OneYearFromNow)}
+ {"Expires", couch_util:rfc1123_date(OneYearFromNow)}
],
couch_httpd:serve_file(Req, "favicon.ico", DocumentRoot, CachingHeaders);
@@ -103,7 +103,7 @@ handle_uuids_req(#httpd{method='GET'}=Req) ->
Etag = couch_httpd:make_etag(UUIDs),
couch_httpd:etag_respond(Req, Etag, fun() ->
CacheBustingHeaders = [
- {"Date", httpd_util:rfc1123_date()},
+ {"Date", couch_util:rfc1123_date()},
{"Cache-Control", "no-cache"},
% Past date, ON PURPOSE!
{"Expires", "Fri, 01 Jan 1990 00:00:00 GMT"},
View
2 src/couchdb/couch_log.erl
@@ -159,7 +159,7 @@ log(#state{fd = Fd}, ConsoleMsg, FileMsg) ->
get_log_messages(Pid, Level, Format, Args) ->
ConsoleMsg = unicode:characters_to_binary(io_lib:format(
"[~s] [~p] " ++ Format ++ "~n", [Level, Pid | Args])),
- FileMsg = ["[", httpd_util:rfc1123_date(), "] ", ConsoleMsg],
+ FileMsg = ["[", couch_util:rfc1123_date(), "] ", ConsoleMsg],
{ConsoleMsg, iolist_to_binary(FileMsg)}.
View
2 src/couchdb/couch_server.erl
@@ -170,7 +170,7 @@ init([]) ->
{ok, #server{root_dir=RootDir,
dbname_regexp=RegExp,
max_dbs_open=MaxDbsOpen,
- start_time=httpd_util:rfc1123_date()}}.
+ start_time=couch_util:rfc1123_date()}}.
terminate(_Reason, _Srv) ->
lists:foreach(
View
42 src/couchdb/couch_util.erl
@@ -28,6 +28,7 @@
-export([url_strip_password/1]).
-export([encode_doc_id/1]).
-export([with_db/2]).
+-export([rfc1123_date/0, rfc1123_date/1]).
-include("couch_db.hrl").
@@ -445,3 +446,44 @@ with_db(DbName, Fun) ->
Else ->
throw(Else)
end.
+
+rfc1123_date() ->
+ {{YYYY,MM,DD},{Hour,Min,Sec}} = calendar:universal_time(),
+ DayNumber = calendar:day_of_the_week({YYYY,MM,DD}),
+ lists:flatten(
+ io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
+ [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
+
+rfc1123_date(undefined) ->
+ undefined;
+rfc1123_date(UniversalTime) ->
+ {{YYYY,MM,DD},{Hour,Min,Sec}} = UniversalTime,
+ DayNumber = calendar:day_of_the_week({YYYY,MM,DD}),
+ lists:flatten(
+ io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT",
+ [day(DayNumber),DD,month(MM),YYYY,Hour,Min,Sec])).
+
+%% day
+
+day(1) -> "Mon";
+day(2) -> "Tue";
+day(3) -> "Wed";
+day(4) -> "Thu";
+day(5) -> "Fri";
+day(6) -> "Sat";
+day(7) -> "Sun".
+
+%% month
+
+month(1) -> "Jan";
+month(2) -> "Feb";
+month(3) -> "Mar";
+month(4) -> "Apr";
+month(5) -> "May";
+month(6) -> "Jun";
+month(7) -> "Jul";
+month(8) -> "Aug";
+month(9) -> "Sep";
+month(10) -> "Oct";
+month(11) -> "Nov";
+month(12) -> "Dec".
View
12 src/mochiweb/mochiweb_cookies.erl
@@ -49,9 +49,9 @@ cookie(Key, Value, Options) ->
RawAge ->
When = case proplists:get_value(local_time, Options) of
undefined ->
- calendar:local_time();
+ calendar:universal_time();
LocalTime ->
- LocalTime
+ calendar:local_time_to_universal_time_dst(LocalTime)
end,
Age = case RawAge < 0 of
true ->
@@ -115,12 +115,12 @@ quote(V0) ->
orelse erlang:error({cookie_quoting_required, V}),
V.
-add_seconds(Secs, LocalTime) ->
- Greg = calendar:datetime_to_gregorian_seconds(LocalTime),
+add_seconds(Secs, UniversalTime) ->
+ Greg = calendar:datetime_to_gregorian_seconds(UniversalTime),
calendar:gregorian_seconds_to_datetime(Greg + Secs).
-age_to_cookie_date(Age, LocalTime) ->
- httpd_util:rfc1123_date(add_seconds(Age, LocalTime)).
+age_to_cookie_date(Age, UniversalTime) ->
+ couch_util:rfc1123_date(add_seconds(Age, UniversalTime)).
%% @spec parse_cookie(string()) -> [{K::string(), V::string()}]
%% @doc Parse the contents of a Cookie header field, ignoring cookie
View
6 src/mochiweb/mochiweb_request.erl
@@ -600,9 +600,9 @@ maybe_redirect(RelPath, FullPath, ExtraHeaders) ->
end.
maybe_serve_file(File, ExtraHeaders) ->
- case file:read_file_info(File) of
+ case file:read_file_info(File, [{time, universal}]) of
{ok, FileInfo} ->
- LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime),
+ LastModified = couch_util:rfc1123_date(FileInfo#file_info.mtime),
case get_header_value("if-modified-since") of
LastModified ->
respond({304, ExtraHeaders, ""});
@@ -626,7 +626,7 @@ maybe_serve_file(File, ExtraHeaders) ->
server_headers() ->
[{"Server", "MochiWeb/1.0 (" ++ ?QUIP ++ ")"},
- {"Date", httpd_util:rfc1123_date()}].
+ {"Date", couch_util:rfc1123_date()}].
make_code(X) when is_integer(X) ->
[integer_to_list(X), [" " | httpd_util:reason_phrase(X)]];

0 comments on commit b1a049b

Please sign in to comment.
Something went wrong with that request. Please try again.