Skip to content

Commit 3b21698

Browse files
plukasewern
authored andcommitted
SAK-40430: Allow SiteStats aggregator job to compensate for sakai_event data stored in a different timezone (sakaiproject#5866)
* SAK-40430: Allow SiteStats aggregator job to compensate for sakai_event data stored in a different timezone * SAK-40430: replacing TimeService with UserTimeService and standardizing display of dates within the tool * SAK-40430: calendar mock fixup
1 parent 0462d02 commit 3b21698

File tree

36 files changed

+486
-113
lines changed

36 files changed

+486
-113
lines changed

calendar/calendar-impl/impl/src/test/org/sakaiproject/calendar/impl/DbCalendarServiceSerializationTest.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.io.InputStreamReader;
2828
import java.sql.Connection;
2929
import java.sql.SQLException;
30+
import java.time.Instant;
31+
import java.time.LocalDate;
3032
import java.util.ArrayList;
3133
import java.util.Date;
3234
import java.util.GregorianCalendar;
@@ -439,7 +441,21 @@ public String dateFormatLong(Date date, Locale locale) {
439441
public String dateTimeFormatLong(Date date, Locale locale) {
440442
return null;
441443
}
442-
444+
445+
@Override
446+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale) {
447+
return null;
448+
}
449+
450+
@Override
451+
public String shortLocalizedTimestamp(Instant instant, Locale locale) {
452+
return null;
453+
}
454+
455+
@Override
456+
public String shortLocalizedDate(LocalDate date, Locale locale) {
457+
return null;
458+
}
443459
};
444460
services = new HashMap<String,Object>();
445461
services.put("sqlservice", sqlService);

kernel/api/src/main/java/org/sakaiproject/time/api/UserTimeService.java

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.sakaiproject.time.api;
22

3+
import java.time.Instant;
4+
import java.time.LocalDate;
35
import java.util.Date;
46
import java.util.Locale;
57
import java.util.TimeZone;
@@ -42,5 +44,33 @@ public interface UserTimeService {
4244
*/
4345
public String dateTimeFormatLong(Date date, Locale locale);
4446

45-
47+
/**
48+
* Formats a point in time, in the given time zone, for display to the user in a concise way that still presents all relevant information
49+
* including date, time, and time zone.
50+
*
51+
* @param instant the instant in time
52+
* @param timezone the time zone to use when displaying the date
53+
* @param locale the locale to use when formatting the date for display
54+
* @return a formatted date/time for presentation to the user
55+
*/
56+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale);
57+
58+
/**
59+
* Formats a point in time, in the user's time zone, for display to the user in a concise way that still presents all relevant information
60+
* including date, time, and time zone.
61+
*
62+
* @param instant the instant in time
63+
* @param locale the locale to use when formatting the date for display
64+
* @return a formatted date/time for presentation to the user
65+
*/
66+
public String shortLocalizedTimestamp(Instant instant, Locale locale);
67+
68+
/**
69+
* Formats a date (month/day/year) in a concise but easily understood format for the given locale.
70+
* Typically presents unambiguous month/day/year values as opposed to a purely 2-digit value for each.
71+
* @param date month/day/year value
72+
* @param locale the locale for use when formatting the date for display
73+
* @return a formatted date for presentation to the user
74+
*/
75+
public String shortLocalizedDate(LocalDate date, Locale locale);
4676
}

kernel/kernel-impl/src/main/java/org/sakaiproject/content/impl/serialize/impl/conversion/ConversionTimeService.java

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
package org.sakaiproject.content.impl.serialize.impl.conversion;
2323

24+
import java.time.Instant;
25+
import java.time.LocalDate;
2426
import java.util.Date;
2527
import java.util.GregorianCalendar;
2628
import java.util.Locale;
@@ -197,4 +199,18 @@ public String dateTimeFormatLong(Date date, Locale locale) {
197199
throw new UnsupportedOperationException("This class is only to be used for conversion purposes");
198200
}
199201

202+
@Override
203+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale) {
204+
throw new UnsupportedOperationException("This class is only to be used for conversion purposes");
205+
}
206+
207+
@Override
208+
public String shortLocalizedTimestamp(Instant instant, Locale locale) {
209+
throw new UnsupportedOperationException("This class is only to be used for conversion purposes");
210+
}
211+
212+
@Override
213+
public String shortLocalizedDate(LocalDate date, Locale locale) {
214+
throw new UnsupportedOperationException("This class is only to be used for conversion purposes");
215+
}
200216
}

kernel/kernel-impl/src/main/java/org/sakaiproject/time/impl/BasicTimeService.java

+16
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.text.DateFormat;
2525
import java.text.SimpleDateFormat;
2626
import java.time.Clock;
27+
import java.time.Instant;
28+
import java.time.LocalDate;
2729
import java.util.Date;
2830
import java.util.GregorianCalendar;
2931
import java.util.Hashtable;
@@ -1021,4 +1023,18 @@ public String dateTimeFormatLong(Date date, Locale locale) {
10211023
return userTimeService.dateTimeFormatLong(date, locale);
10221024
}
10231025

1026+
@Override
1027+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale) {
1028+
return userTimeService.shortLocalizedTimestamp(instant, timezone, locale);
1029+
}
1030+
1031+
@Override
1032+
public String shortLocalizedTimestamp(Instant instant, Locale locale) {
1033+
return userTimeService.shortLocalizedTimestamp(instant, locale);
1034+
}
1035+
1036+
@Override
1037+
public String shortLocalizedDate(LocalDate date, Locale locale) {
1038+
return userTimeService.shortLocalizedDate(date, locale);
1039+
}
10241040
}

kernel/kernel-impl/src/main/java/org/sakaiproject/time/impl/UserTimeServiceImpl.java

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package org.sakaiproject.time.impl;
22

33
import java.text.DateFormat;
4+
import java.time.Instant;
5+
import java.time.LocalDate;
6+
import java.time.ZonedDateTime;
7+
import java.time.format.DateTimeFormatter;
8+
import java.time.format.DateTimeFormatterBuilder;
9+
import java.time.format.FormatStyle;
10+
import java.time.format.TextStyle;
411
import java.util.Date;
512
import java.util.Locale;
613
import java.util.TimeZone;
@@ -116,4 +123,24 @@ public String dateTimeFormatLong(Date date, Locale locale) {
116123
return d;
117124
}
118125

126+
@Override
127+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale) {
128+
ZonedDateTime userDate = ZonedDateTime.ofInstant(instant, timezone.toZoneId());
129+
DateTimeFormatter userFormatter = new DateTimeFormatterBuilder()
130+
.appendLocalized(FormatStyle.MEDIUM, FormatStyle.SHORT)
131+
.appendLiteral(" ").appendZoneText(TextStyle.SHORT)
132+
.toFormatter(locale);
133+
return userDate.format(userFormatter);
134+
}
135+
136+
@Override
137+
public String shortLocalizedTimestamp(Instant instant, Locale locale) {
138+
return shortLocalizedTimestamp(instant, getLocalTimeZone(), locale);
139+
}
140+
141+
@Override
142+
public String shortLocalizedDate(LocalDate date, Locale locale) {
143+
DateTimeFormatter df = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale);
144+
return date.format(df);
145+
}
119146
}

kernel/kernel-impl/src/test/java/org/sakaiproject/content/impl/serialize/impl/test/MockTimeService.java

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
package org.sakaiproject.content.impl.serialize.impl.test;
2323

24+
import java.time.Instant;
25+
import java.time.LocalDate;
2426
import java.util.Date;
2527
import java.util.GregorianCalendar;
2628
import java.util.Locale;
@@ -216,4 +218,18 @@ public String dateTimeFormatLong(Date date, Locale locale) {
216218
return null;
217219
}
218220

221+
@Override
222+
public String shortLocalizedTimestamp(Instant instant, TimeZone timezone, Locale locale) {
223+
return null;
224+
}
225+
226+
@Override
227+
public String shortLocalizedTimestamp(Instant instant, Locale locale) {
228+
return null;
229+
}
230+
231+
@Override
232+
public String shortLocalizedDate(LocalDate date, Locale locale) {
233+
return null;
234+
}
219235
}

sitestats/sitestats-api/src/java/org/sakaiproject/sitestats/api/StatsManager.java

+3
Original file line numberDiff line numberDiff line change
@@ -643,4 +643,7 @@ public int getResourceStatsRowCount(
643643
/** Logs an event using EventTrackingService. */
644644
public void logEvent(Object object, String logAction, String siteId, boolean oncePerSession);
645645

646+
/** Get the local sakai name (from ui.service property) */
647+
public String getLocalSakaiName();
648+
646649
}

sitestats/sitestats-api/src/java/org/sakaiproject/sitestats/api/report/Report.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.sakaiproject.sitestats.api.EventStat;
2626
import org.sakaiproject.sitestats.api.ResourceStat;
2727
import org.sakaiproject.sitestats.api.Stat;
28-
import org.sakaiproject.time.cover.TimeService;
2928

3029

3130
public class Report implements Serializable {
@@ -59,10 +58,7 @@ public void setReportDefinition(ReportDef reportDef) {
5958
public Date getReportGenerationDate() {
6059
return reportGenerationDate;
6160
}
62-
/** Get the localized date the report was generated. */
63-
public String getLocalizedReportGenerationDate() {
64-
return TimeService.newTime(reportGenerationDate.getTime()).toStringLocalFull();
65-
}
61+
6662
/** Set the localized date the report was generated. */
6763
public void setReportGenerationDate(Date reportGenerationDate) {
6864
this.reportGenerationDate = reportGenerationDate;

sitestats/sitestats-api/src/java/org/sakaiproject/sitestats/api/report/ReportParams.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
package org.sakaiproject.sitestats.api.report;
2020

2121
import java.io.Serializable;
22+
import java.time.ZoneId;
23+
import java.time.ZonedDateTime;
24+
import java.time.temporal.ChronoUnit;
2225
import java.util.ArrayList;
23-
import java.util.Calendar;
2426
import java.util.Date;
2527
import java.util.List;
2628

@@ -65,14 +67,12 @@ public ReportParams(){
6567
public ReportParams(String siteId){
6668
this.siteId = siteId;
6769
whatToolIds.add(ReportManager.WHAT_EVENTS_ALLTOOLS);
68-
whenFrom = new Date();
69-
Calendar c = Calendar.getInstance();
70-
c.add(Calendar.DAY_OF_MONTH, -1);
71-
c.set(Calendar.HOUR_OF_DAY, 0);
72-
c.set(Calendar.MINUTE, 0);
73-
c.set(Calendar.SECOND, 0);
74-
whenFrom = c.getTime();
75-
whenTo = new Date();
70+
// events are counted against a particular date using the server time zone, so initialize the date
71+
// range based on the current date in that time zone
72+
ZonedDateTime today = ZonedDateTime.now(ZoneId.systemDefault()).truncatedTo(ChronoUnit.DAYS);
73+
ZonedDateTime yesterday = today.minusDays(1);
74+
whenFrom = Date.from(yesterday.toInstant());
75+
whenTo = Date.from(today.toInstant());
7676
}
7777

7878
public ReportParams(String siteId, String what, List<String> whatToolIds, List<String> whatEventIds, String whatResourceAction, List<String> whatResourceIds, String when, Date whenFrom, Date whenTo, String who, String whoRoleId, String whoGroupId, List<String> whoUserIds) {

sitestats/sitestats-bundle/src/resources/Messages.properties

+8-2
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,13 @@ reportres_title=Report
234234
reportres_title_detailed=Report: '${title}'
235235
reportres_summ_description=Description:
236236
reportres_summ_site=Site:
237-
reportres_summ_generatedon=Report date:
237+
reportres_summ_generatedon=Report generated:
238238
reportres_summ_act_basedon=Activity type:
239239
reportres_summ_act_tools_selected=Tools selected:
240240
reportres_summ_act_events_selected=Events selected:
241241
reportres_summ_act_rsrc_action=Resources action:
242242
reportres_summ_act_rsrc_selected=Resources selected:
243-
reportres_summ_timeperiod=Time period:
243+
reportres_summ_timeperiod=Date range:
244244
reportres_summ_usr_selectiontype=User selection type:
245245
reportres_summ_usr_group_selected=Group selected:
246246
reportres_summ_usr_role_selected=Role selected:
@@ -325,3 +325,9 @@ predefined_report5_description = Show users who have never visited the site.
325325
#
326326
predefined_report6_title = Users with no activity
327327
predefined_report6_description = Show users with no activity in site.
328+
329+
# Dates
330+
lastJobRun_server_time=({0} server time: {1})
331+
widget_server_time_msg=All dates use the {0} server time zone.
332+
report_server_time_zone=({0} server time zone)
333+

sitestats/sitestats-impl/src/java/org/sakaiproject/sitestats/impl/StatsAggregateJobImpl.java

+22-1
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
import java.sql.SQLException;
2626
import java.sql.Statement;
2727
import java.util.ArrayList;
28+
import java.util.Calendar;
2829
import java.util.Date;
2930
import java.util.List;
31+
import java.util.TimeZone;
3032

3133
import lombok.extern.slf4j.Slf4j;
34+
import org.apache.commons.lang.StringUtils;
3235
import org.quartz.JobExecutionContext;
3336
import org.quartz.JobExecutionException;
3437
import org.quartz.SchedulerException;
@@ -47,6 +50,7 @@ public class StatsAggregateJobImpl implements StatefulJob {
4750
private int sqlBlockSize = 1000;
4851
private long startEventId = -1;
4952
private long lastEventIdInTable = -1;
53+
private String sakaiEventTimeZone = "";
5054

5155
private String driverClassName = null;
5256
private String url = null;
@@ -281,7 +285,16 @@ private String startJob() throws SQLException {
281285
String sessionId = null;
282286
try{
283287
//If an exception is launched, iteration is not aborted but no event is added to event queue
284-
date = new Date(rs.getTimestamp("EVENT_DATE").getTime());
288+
289+
// Daily events can only be counted relative to a single time zone (server time). The sakai_event table
290+
// may be storing dates in a time zone different than this. Adjust for the sakai_event time zone if provided.
291+
if (StringUtils.isNotBlank(sakaiEventTimeZone)) {
292+
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(sakaiEventTimeZone));
293+
date = new Date(rs.getTimestamp("EVENT_DATE", calendar).getTime());
294+
} else {
295+
date = new Date(rs.getTimestamp("EVENT_DATE").getTime());
296+
}
297+
285298
event = rs.getString("EVENT");
286299
ref = rs.getString("REF");
287300
sessionUser = rs.getString("SESSION_USER");
@@ -633,6 +646,14 @@ public void setStartEventId(long startEventId) {
633646
this.startEventId = startEventId;
634647
}
635648

649+
public String getSakaiEventTimeZone() {
650+
return sakaiEventTimeZone;
651+
}
652+
653+
public void setSakaiEventTimeZone(String timeZone) {
654+
sakaiEventTimeZone = timeZone;
655+
}
656+
636657
public String getDriverClassName() {
637658
return driverClassName;
638659
}

sitestats/sitestats-impl/src/java/org/sakaiproject/sitestats/impl/StatsManagerImpl.java

+8
Original file line numberDiff line numberDiff line change
@@ -3885,6 +3885,14 @@ public void logEvent(Object object, String logAction, String siteId, boolean onc
38853885
}
38863886
}
38873887

3888+
/* (non-Javadoc)
3889+
* @see org.sakaiproject.sitestats.api.StatsManager#getLocalSakaiName()
3890+
*/
3891+
@Override
3892+
public String getLocalSakaiName() {
3893+
return M_scs.getString("ui.service", "Sakai");
3894+
}
3895+
38883896
private void checkForEventContextSupport() {
38893897
try{
38903898
Event.class.getMethod("getContext", null);

0 commit comments

Comments
 (0)