2 * Sone - GetTimesAjaxPage.java - Copyright © 2010–2013 David Roden
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free Software
6 * Foundation, either version 3 of the License, or (at your option) any later
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.web.ajax;
20 import static com.fasterxml.jackson.databind.node.JsonNodeFactory.instance;
22 import java.text.DateFormat;
23 import java.text.SimpleDateFormat;
24 import java.util.Date;
25 import java.util.concurrent.TimeUnit;
27 import net.pterodactylus.sone.data.Post;
28 import net.pterodactylus.sone.data.PostReply;
29 import net.pterodactylus.sone.web.WebInterface;
30 import net.pterodactylus.sone.web.page.FreenetRequest;
32 import com.fasterxml.jackson.databind.node.ObjectNode;
33 import com.google.common.base.Optional;
36 * Ajax page that returns a formatted, relative timestamp for replies or posts.
38 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
40 public class GetTimesAjaxPage extends JsonPage {
42 /** Formatter for tooltips. */
43 private static final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy, HH:mm:ss");
46 * Creates a new get times AJAX page.
49 * The Sone web interface
51 public GetTimesAjaxPage(WebInterface webInterface) {
52 super("getTimes.ajax", webInterface);
56 protected JsonReturnObject createJsonObject(FreenetRequest request) {
57 String allIds = request.getHttpRequest().getParam("posts");
58 ObjectNode postTimes = new ObjectNode(instance);
59 if (allIds.length() > 0) {
60 String[] ids = allIds.split(",");
61 for (String id : ids) {
62 Optional<Post> post = webInterface.getCore().getDatabase().getPost(id);
63 if (!post.isPresent()) {
66 ObjectNode postTime = new ObjectNode(instance);
67 Time time = getTime(post.get().getTime());
68 postTime.put("timeText", time.getText());
69 postTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
70 synchronized (dateFormat) {
71 postTime.put("tooltip", dateFormat.format(new Date(post.get().getTime())));
73 postTimes.put(id, postTime);
76 ObjectNode replyTimes = new ObjectNode(instance);
77 allIds = request.getHttpRequest().getParam("replies");
78 if (allIds.length() > 0) {
79 String[] ids = allIds.split(",");
80 for (String id : ids) {
81 Optional<PostReply> reply = webInterface.getCore().getDatabase().getPostReply(id);
82 if (!reply.isPresent()) {
85 ObjectNode replyTime = new ObjectNode(instance);
86 Time time = getTime(reply.get().getTime());
87 replyTime.put("timeText", time.getText());
88 replyTime.put("refreshTime", TimeUnit.MILLISECONDS.toSeconds(time.getRefresh()));
89 synchronized (dateFormat) {
90 replyTime.put("tooltip", dateFormat.format(new Date(reply.get().getTime())));
92 replyTimes.put(id, replyTime);
95 return createSuccessJsonObject().put("postTimes", postTimes).put("replyTimes", replyTimes);
99 protected boolean needsFormPassword() {
104 protected boolean requiresLogin() {
113 * Returns the formatted relative time for a given time.
116 * The time to format the difference from (in milliseconds)
117 * @return The formatted age
119 private Time getTime(long time) {
120 return getTime(webInterface, time);
128 * Returns the formatted relative time for a given time.
130 * @param webInterface
131 * The Sone web interface (for l10n access)
133 * The time to format the difference from (in milliseconds)
134 * @return The formatted age
136 public static Time getTime(WebInterface webInterface, long time) {
138 return new Time(webInterface.getL10n().getString("View.Sone.Text.UnknownDate"), TimeUnit.HOURS.toMillis(12));
140 long age = System.currentTimeMillis() - time;
144 text = webInterface.getL10n().getDefaultString("View.Time.InTheFuture");
145 refresh = TimeUnit.MINUTES.toMillis(5);
146 } else if (age < TimeUnit.SECONDS.toMillis(20)) {
147 text = webInterface.getL10n().getDefaultString("View.Time.AFewSecondsAgo");
148 refresh = TimeUnit.SECONDS.toMillis(10);
149 } else if (age < TimeUnit.SECONDS.toMillis(45)) {
150 text = webInterface.getL10n().getString("View.Time.HalfAMinuteAgo");
151 refresh = TimeUnit.SECONDS.toMillis(20);
152 } else if (age < TimeUnit.SECONDS.toMillis(90)) {
153 text = webInterface.getL10n().getString("View.Time.AMinuteAgo");
154 refresh = TimeUnit.MINUTES.toMillis(1);
155 } else if (age < TimeUnit.MINUTES.toMillis(30)) {
156 text = webInterface.getL10n().getString("View.Time.XMinutesAgo", "min", String.valueOf(TimeUnit.MILLISECONDS.toMinutes(age + TimeUnit.SECONDS.toMillis(30))));
157 refresh = TimeUnit.MINUTES.toMillis(1);
158 } else if (age < TimeUnit.MINUTES.toMillis(45)) {
159 text = webInterface.getL10n().getString("View.Time.HalfAnHourAgo");
160 refresh = TimeUnit.MINUTES.toMillis(10);
161 } else if (age < TimeUnit.MINUTES.toMillis(90)) {
162 text = webInterface.getL10n().getString("View.Time.AnHourAgo");
163 refresh = TimeUnit.HOURS.toMillis(1);
164 } else if (age < TimeUnit.HOURS.toMillis(21)) {
165 text = webInterface.getL10n().getString("View.Time.XHoursAgo", "hour", String.valueOf(TimeUnit.MILLISECONDS.toHours(age + TimeUnit.MINUTES.toMillis(30))));
166 refresh = TimeUnit.HOURS.toMillis(1);
167 } else if (age < TimeUnit.HOURS.toMillis(42)) {
168 text = webInterface.getL10n().getString("View.Time.ADayAgo");
169 refresh = TimeUnit.DAYS.toMillis(1);
170 } else if (age < TimeUnit.DAYS.toMillis(6)) {
171 text = webInterface.getL10n().getString("View.Time.XDaysAgo", "day", String.valueOf(TimeUnit.MILLISECONDS.toDays(age + TimeUnit.HOURS.toMillis(12))));
172 refresh = TimeUnit.DAYS.toMillis(1);
173 } else if (age < TimeUnit.DAYS.toMillis(11)) {
174 text = webInterface.getL10n().getString("View.Time.AWeekAgo");
175 refresh = TimeUnit.DAYS.toMillis(1);
176 } else if (age < TimeUnit.DAYS.toMillis(28)) {
177 text = webInterface.getL10n().getString("View.Time.XWeeksAgo", "week", String.valueOf((TimeUnit.MILLISECONDS.toHours(age) + 84) / (7 * 24)));
178 refresh = TimeUnit.DAYS.toMillis(1);
179 } else if (age < TimeUnit.DAYS.toMillis(42)) {
180 text = webInterface.getL10n().getString("View.Time.AMonthAgo");
181 refresh = TimeUnit.DAYS.toMillis(1);
182 } else if (age < TimeUnit.DAYS.toMillis(330)) {
183 text = webInterface.getL10n().getString("View.Time.XMonthsAgo", "month", String.valueOf((TimeUnit.MILLISECONDS.toDays(age) + 15) / 30));
184 refresh = TimeUnit.DAYS.toMillis(1);
185 } else if (age < TimeUnit.DAYS.toMillis(540)) {
186 text = webInterface.getL10n().getString("View.Time.AYearAgo");
187 refresh = TimeUnit.DAYS.toMillis(7);
189 text = webInterface.getL10n().getString("View.Time.XYearsAgo", "year", String.valueOf((long) ((TimeUnit.MILLISECONDS.toDays(age) + 182.64) / 365.28)));
190 refresh = TimeUnit.DAYS.toMillis(7);
192 return new Time(text, refresh);
196 * Container for a formatted time.
198 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
200 public static class Time {
202 /** The formatted time. */
203 private final String text;
205 /** The time after which to refresh the time. */
206 private final long refresh;
209 * Creates a new formatted time container.
214 * The time after which to refresh the time (in milliseconds)
216 public Time(String text, long refresh) {
218 this.refresh = refresh;
222 * Returns the formatted time.
224 * @return The formatted time
226 public String getText() {
231 * Returns the time after which to refresh the time.
233 * @return The time after which to refresh the time (in milliseconds)
235 public long getRefresh() {
243 public String toString() {