Time formatter utilities
This commit is contained in:
parent
a76d5cb1ac
commit
0373867875
|
@ -99,5 +99,6 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -215,8 +215,6 @@ public class RecipeDetailBean implements Serializable {
|
|||
@PostConstruct
|
||||
private void init() {
|
||||
this.recipe = userSession.getRecipe();
|
||||
|
||||
log.info("Using recipe: " + this.recipe);
|
||||
/**
|
||||
* For "create new, this recipe is a blank constructed
|
||||
* and passed from main page. For Detail display, it's
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import com.mousetech.gourmetj.persistence.model.Category;
|
||||
import com.mousetech.gourmetj.persistence.model.Recipe;
|
||||
import com.mousetech.gourmetj.utils.TimeFormatter;
|
||||
|
||||
@Named
|
||||
@SessionScoped
|
||||
|
@ -123,46 +124,15 @@ public class UserSession implements Serializable {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
//** Util, consider conversion to JSF Converter
|
||||
public String formatTime(Long ltime) {
|
||||
if (ltime == null) {
|
||||
return "";
|
||||
}
|
||||
int time = ltime.intValue();
|
||||
int dd, hh, mm, ss;
|
||||
ss = time % 60;
|
||||
time /= 60;
|
||||
mm = time % 60;
|
||||
time /= 60;
|
||||
hh = time % 24;
|
||||
dd = time / 24;
|
||||
StringBuffer sb = new StringBuffer(20);
|
||||
if (dd > 0) {
|
||||
sb.append(dd).append("d ");
|
||||
}
|
||||
if (hh > 0) {
|
||||
sb.append(hh).append("h ");
|
||||
}
|
||||
if (mm > 0) {
|
||||
sb.append(mm);
|
||||
if ((ss == 0) && (hh == 0)) {
|
||||
sb.append(" minutes");
|
||||
} else {
|
||||
sb.append("min. ");
|
||||
}
|
||||
}
|
||||
if (ss > 0) {
|
||||
sb.append(dd).append("sec. ");
|
||||
}
|
||||
return sb.toString().trim();
|
||||
return TimeFormatter.formatTime(ltime);
|
||||
}
|
||||
|
||||
// Primefaces handle session timeout
|
||||
|
||||
/**
|
||||
* Session timeout, msec.
|
||||
*/
|
||||
private long sessionTimeoutInterval = 300000;
|
||||
|
||||
// Session timeout, ms
|
||||
long sessionTimeoutInterval = 30000L;
|
||||
|
||||
/**
|
||||
* @return the sessionTimeoutInterval
|
||||
*/
|
||||
|
@ -176,7 +146,8 @@ public class UserSession implements Serializable {
|
|||
.executeScript("sessionExpiredConfirmation.show()");
|
||||
}
|
||||
|
||||
public void logoutAction() {
|
||||
public String logoutAction() {
|
||||
log.warn("Session Idle listener logout");
|
||||
return "/main.jsf";
|
||||
}
|
||||
}
|
||||
|
|
181
src/main/java/com/mousetech/gourmetj/utils/TimeFormatter.java
Normal file
181
src/main/java/com/mousetech/gourmetj/utils/TimeFormatter.java
Normal file
|
@ -0,0 +1,181 @@
|
|||
package com.mousetech.gourmetj.utils;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Handle conversion of complex time fields where days, hours,
|
||||
* minutes and seconds may be present as separate entities.
|
||||
*
|
||||
* @author timh
|
||||
* @since Jan 8, 2022
|
||||
*/
|
||||
public class TimeFormatter {
|
||||
|
||||
/* Logger */
|
||||
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(TimeFormatter.class);
|
||||
|
||||
public static String formatTime(Long ltime) {
|
||||
if (ltime == null) {
|
||||
return "";
|
||||
}
|
||||
int time = ltime.intValue();
|
||||
int dd, hh, mm, ss;
|
||||
ss = time % 60;
|
||||
time /= 60;
|
||||
mm = time % 60;
|
||||
time /= 60;
|
||||
hh = time % 24;
|
||||
dd = time / 24;
|
||||
StringBuffer sb = new StringBuffer(20);
|
||||
if (dd > 0) {
|
||||
sb.append(dd).append("d ");
|
||||
}
|
||||
if (hh > 0) {
|
||||
sb.append(hh).append("h ");
|
||||
}
|
||||
if (mm > 0) {
|
||||
sb.append(mm);
|
||||
if ((ss == 0) && (hh == 0)) {
|
||||
sb.append(" minutes");
|
||||
} else {
|
||||
sb.append("min. ");
|
||||
}
|
||||
}
|
||||
if (ss > 0) {
|
||||
sb.append(dd).append("sec. ");
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
// private enum MunchUnit {
|
||||
// mu_NONE, mu_DAY, mu_HOUR, mu_MINUTE, mw_SECOND
|
||||
// }
|
||||
|
||||
private static class TimeMuncher {
|
||||
|
||||
public class MunchException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
||||
final private String SPAT_DAYS = "days?|d";
|
||||
final private String SPAT_HOURS = "hours?|h|hr";
|
||||
final private String SPAT_MINUTES = "minutes?|mins?|m";
|
||||
final private String SPAT_SECONDS = "seconds?|secs?|s";
|
||||
|
||||
final Pattern pat_number;
|
||||
final Pattern pat_days;
|
||||
final Pattern pat_hours;
|
||||
final Pattern pat_mins;
|
||||
final Pattern pat_secs;
|
||||
|
||||
final Scanner scanner;
|
||||
|
||||
public TimeMuncher(String timestr) {
|
||||
pat_number =
|
||||
Pattern.compile("(\\d[\\,\\.]?\\d*)?(.*)");
|
||||
// Compile here for future I18N support
|
||||
pat_days = Pattern.compile(SPAT_DAYS);
|
||||
pat_hours = Pattern.compile(SPAT_HOURS);
|
||||
pat_mins = Pattern.compile(SPAT_MINUTES);
|
||||
pat_secs = Pattern.compile(SPAT_SECONDS);
|
||||
|
||||
scanner = new Scanner(timestr);
|
||||
scanner.useDelimiter("\\W");
|
||||
}
|
||||
|
||||
public Long scan() {
|
||||
Double sum = null;
|
||||
Double dvalue = null;
|
||||
|
||||
try {
|
||||
while (scanner.hasNext()) {
|
||||
if (scanner.hasNextDouble()) {
|
||||
dvalue = scanner.nextDouble();
|
||||
} else {
|
||||
String units = scanner.next();
|
||||
sum = setSum(sum, dvalue, units);
|
||||
dvalue = null;
|
||||
}
|
||||
}
|
||||
} catch (MunchException e) {
|
||||
log.warn("Unparseable time value");
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (sum == null) {
|
||||
return null;
|
||||
}
|
||||
return sum.longValue();
|
||||
}
|
||||
|
||||
private Double setSum(Double sum, Double dvalue,
|
||||
String units) throws MunchException {
|
||||
Matcher m;
|
||||
|
||||
m = pat_number.matcher(units);
|
||||
|
||||
if (!m.matches()) {
|
||||
throw new MunchException();
|
||||
}
|
||||
if (m.group(1) != null) {
|
||||
String a = m.group(1);
|
||||
if (dvalue != null) {
|
||||
throw new MunchException();
|
||||
}
|
||||
dvalue = Double
|
||||
.valueOf(a);
|
||||
//units = units.substring(m.end());
|
||||
}
|
||||
units = m.group(2);
|
||||
m = pat_days.matcher(units);
|
||||
if (m.matches()) {
|
||||
return addToSum(sum, dvalue,
|
||||
24L * 60L * 60L * 1000L);
|
||||
}
|
||||
m = pat_hours.matcher(units);
|
||||
if (m.matches()) {
|
||||
return addToSum(sum, dvalue, 60L * 60L * 1000L);
|
||||
}
|
||||
m = pat_mins.matcher(units);
|
||||
if (m.matches()) {
|
||||
return addToSum(sum, dvalue, 60L * 1000L);
|
||||
}
|
||||
m = pat_secs.matcher(units);
|
||||
if (m.matches()) {
|
||||
return addToSum(sum, dvalue, 1000L);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private Double addToSum(Double sum, Double dvalue,
|
||||
long l) throws MunchException {
|
||||
if (dvalue == null) {
|
||||
throw new TimeMuncher.MunchException();
|
||||
}
|
||||
dvalue *= l;
|
||||
if (sum == null) {
|
||||
sum = 0.0;
|
||||
}
|
||||
sum += dvalue;
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
public static Long parseTime(String timestr) {
|
||||
TimeMuncher muncher = new TimeMuncher(timestr);
|
||||
|
||||
Long interval = muncher.scan();
|
||||
return interval;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package com.mousetech.gourmetj.utils;
|
|
@ -40,16 +40,16 @@
|
|||
</p:idleMonitor>
|
||||
<p:confirmDialog closable="false"
|
||||
id="sessionExpiredDlg"
|
||||
message="Your session expired."
|
||||
message="Your session has expired."
|
||||
header="#{msgs['confirmDialog.initiatingDestroyProcess.label']}"
|
||||
severity="alert"
|
||||
widgetVar="sessionExpiredConfirmation"
|
||||
style="z-index: 25000"
|
||||
>
|
||||
<p:commandButton id="confirmRouteDel"
|
||||
value="Ok"
|
||||
oncomplete="PF('sessionExpiredDlg').hide()"
|
||||
actionListener="#{userSession.logoutAction}"
|
||||
<p:commandButton id="cmdExpiredOK"
|
||||
value="OK"
|
||||
action="/main.jsf"
|
||||
oncomplete="PF('sessionExpiredConfirmation').hide()"
|
||||
/>
|
||||
</p:confirmDialog>
|
||||
</h:form>
|
||||
|
|
|
@ -360,10 +360,12 @@
|
|||
</p:tabView>
|
||||
<p:commandButton id="doSave" value="Save"
|
||||
icon="ui-icon-pencil"
|
||||
ajax="false"
|
||||
disabled="{not recipeDetailBean.dirty}"
|
||||
action="#{recipeDetailBean.doSave}"
|
||||
/>
|
||||
<p:commandButton id="doCancel" value="Cancel"
|
||||
ajax="false"
|
||||
immediate="true" action="recipeDetails.jsf"
|
||||
/>
|
||||
</h:form>
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<html>
|
||||
<head>
|
||||
<title>ERROR - Page Expired</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Page Expired</h1>
|
||||
<p>The page state could not be restored because it was left
|
||||
idle too long.</p>
|
||||
<p><a href="/main.jsf">Return to Main Page</a></p>
|
||||
<p>The page state could not be restored because it was
|
||||
left idle too long.</p>
|
||||
<p>
|
||||
<a href="/main.jsf">Return to Main Page</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
|
@ -45,12 +45,12 @@
|
|||
columns="2"
|
||||
>
|
||||
<p:commandButton
|
||||
value="Back"
|
||||
value="Back" ajax="false"
|
||||
icon="ui-icon-arrowthick-1-w"
|
||||
action="main.jsf"
|
||||
immediate="true"
|
||||
/>
|
||||
<p:commandButton
|
||||
<p:commandButton ajax="false"
|
||||
value="Print"
|
||||
icon="ui-icon-print"
|
||||
action="recipePrint.jsf"
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright (C) 2022, Tim Holloway
|
||||
*
|
||||
* Date written: Jan 8, 2022
|
||||
* Author: Tim Holloway <timh@mousetech.com>
|
||||
*/
|
||||
package com.mousetech.gourmetj.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author timh
|
||||
* @since Jan 8, 2022
|
||||
*/
|
||||
class TimeFormatterTest {
|
||||
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@BeforeAll
|
||||
static void setUpBeforeClass() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertEquals(5000, TimeFormatter.parseTime("5s"));
|
||||
assertEquals(5000*60, TimeFormatter.parseTime("5m"));
|
||||
|
||||
assertEquals(3600_000 + 25*60_000, TimeFormatter.parseTime("1 hour, 25 min"));
|
||||
|
||||
assertEquals(5*3600000 + 6*60000, TimeFormatter.parseTime("5h 6m"));
|
||||
assertEquals(277562000L, TimeFormatter.parseTime("3d 5h 6m 2s"));
|
||||
|
||||
assertEquals(18000000L, TimeFormatter.parseTime("1.5 hours"));
|
||||
|
||||
assertEquals(3*3600_000, TimeFormatter.parseTime("3 hours"));
|
||||
|
||||
assertNull(TimeFormatter.parseTime("1 week"));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user