mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Better/more timezone support
This commit is contained in:
@ -53,6 +53,9 @@ public class QSession implements Serializable
|
|||||||
// implementation-specific custom values
|
// implementation-specific custom values
|
||||||
private Map<String, String> values;
|
private Map<String, String> values;
|
||||||
|
|
||||||
|
public static final String VALUE_KEY_USER_TIMEZONE = "UserTimezone";
|
||||||
|
public static final String VALUE_KEY_USER_TIMEZONE_OFFSET_MINUTES = "UserTimezoneOffsetMinutes";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -453,6 +456,7 @@ public class QSession implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Fluent setter for user
|
** Fluent setter for user
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -462,5 +466,4 @@ public class QSession implements Serializable
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,10 @@ import java.time.temporal.ChronoUnit;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -674,7 +676,7 @@ public class ValueUtils
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
LocalDateTime givenZonesNow = LocalDateTime.ofInstant(Instant.now(), zone);
|
LocalDateTime givenZonesNow = LocalDateTime.ofInstant(Instant.now(), zone);
|
||||||
LocalDateTime startOfDay = givenZonesNow.truncatedTo(ChronoUnit.DAYS);
|
LocalDateTime startOfDay = givenZonesNow.truncatedTo(ChronoUnit.DAYS);
|
||||||
return (startOfDay.toInstant(zone.getRules().getOffset(computerTime)));
|
return (startOfDay.toInstant(zone.getRules().getOffset(startOfDay)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -700,7 +702,7 @@ public class ValueUtils
|
|||||||
.with(ChronoField.MINUTE_OF_DAY, 0)
|
.with(ChronoField.MINUTE_OF_DAY, 0)
|
||||||
.with(ChronoField.SECOND_OF_DAY, 0)
|
.with(ChronoField.SECOND_OF_DAY, 0)
|
||||||
.with(ChronoField.NANO_OF_DAY, 0);
|
.with(ChronoField.NANO_OF_DAY, 0);
|
||||||
return (startOfMonth.toInstant(zone.getRules().getOffset(computerTime)));
|
return (startOfMonth.toInstant(zone.getRules().getOffset(startOfMonth)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -720,13 +722,13 @@ public class ValueUtils
|
|||||||
// get date time for now in given zone, truncate it and add offset from utc //
|
// get date time for now in given zone, truncate it and add offset from utc //
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
LocalDateTime givenZonesNow = LocalDateTime.ofInstant(Instant.now(), zone);
|
LocalDateTime givenZonesNow = LocalDateTime.ofInstant(Instant.now(), zone);
|
||||||
LocalDateTime startOfMonth = givenZonesNow
|
LocalDateTime startOfYear = givenZonesNow
|
||||||
.withDayOfYear(1)
|
.withDayOfYear(1)
|
||||||
.with(ChronoField.HOUR_OF_DAY, 0)
|
.with(ChronoField.HOUR_OF_DAY, 0)
|
||||||
.with(ChronoField.MINUTE_OF_DAY, 0)
|
.with(ChronoField.MINUTE_OF_DAY, 0)
|
||||||
.with(ChronoField.SECOND_OF_DAY, 0)
|
.with(ChronoField.SECOND_OF_DAY, 0)
|
||||||
.with(ChronoField.NANO_OF_DAY, 0);
|
.with(ChronoField.NANO_OF_DAY, 0);
|
||||||
return (startOfMonth.toInstant(zone.getRules().getOffset(computerTime)));
|
return (startOfYear.toInstant(zone.getRules().getOffset(startOfYear)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -753,4 +755,28 @@ public class ValueUtils
|
|||||||
return (null);
|
return (null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Get the (time) zoneId either for the current user session (based on session
|
||||||
|
** value UserTimezone or UserTimezoneOffsetMinutes), else the instance's
|
||||||
|
** defaultTimeZoneId string.
|
||||||
|
*******************************************************************************/
|
||||||
|
public static ZoneId getSessionOrInstanceZoneId()
|
||||||
|
{
|
||||||
|
String timezone = QContext.getQSession().getValue(QSession.VALUE_KEY_USER_TIMEZONE);
|
||||||
|
if(StringUtils.hasContent(timezone))
|
||||||
|
{
|
||||||
|
return (ZoneId.of(timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
String userTimezoneOffsetMinutesString = QContext.getQSession().getValue(QSession.VALUE_KEY_USER_TIMEZONE_OFFSET_MINUTES);
|
||||||
|
if(StringUtils.hasContent(userTimezoneOffsetMinutesString))
|
||||||
|
{
|
||||||
|
return (ZoneId.ofOffset("UTC", ZoneOffset.ofTotalSeconds(60 * Integer.parseInt(userTimezoneOffsetMinutesString))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ZoneId.of(QContext.getQInstance().getDefaultTimeZoneId()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,13 @@ import java.time.LocalDate;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.time.Month;
|
import java.time.Month;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import com.kingsrook.qqq.backend.core.BaseTest;
|
import com.kingsrook.qqq.backend.core.BaseTest;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
@ -268,7 +271,7 @@ class ValueUtilsTest extends BaseTest
|
|||||||
assertEquals("1", ValueUtils.getValueAsType(String.class, 1));
|
assertEquals("1", ValueUtils.getValueAsType(String.class, 1));
|
||||||
assertEquals(BigDecimal.ONE, ValueUtils.getValueAsType(BigDecimal.class, 1));
|
assertEquals(BigDecimal.ONE, ValueUtils.getValueAsType(BigDecimal.class, 1));
|
||||||
assertEquals(true, ValueUtils.getValueAsType(Boolean.class, "true"));
|
assertEquals(true, ValueUtils.getValueAsType(Boolean.class, "true"));
|
||||||
assertArrayEquals("a" .getBytes(StandardCharsets.UTF_8), ValueUtils.getValueAsType(byte[].class, "a"));
|
assertArrayEquals("a".getBytes(StandardCharsets.UTF_8), ValueUtils.getValueAsType(byte[].class, "a"));
|
||||||
assertThrows(QValueException.class, () -> ValueUtils.getValueAsType(Serializable.class, 1));
|
assertThrows(QValueException.class, () -> ValueUtils.getValueAsType(Serializable.class, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,4 +295,21 @@ class ValueUtilsTest extends BaseTest
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testGetSessionOrInstanceZoneId()
|
||||||
|
{
|
||||||
|
assertEquals(ZoneId.of("UTC"), ValueUtils.getSessionOrInstanceZoneId());
|
||||||
|
|
||||||
|
QContext.getQInstance().setDefaultTimeZoneId("America/Chicago");
|
||||||
|
assertEquals(ZoneId.of("America/Chicago"), ValueUtils.getSessionOrInstanceZoneId());
|
||||||
|
|
||||||
|
QContext.getQSession().setValue(QSession.VALUE_KEY_USER_TIMEZONE_OFFSET_MINUTES, "-300");
|
||||||
|
assertEquals(ZoneId.of("UTC-05:00"), ValueUtils.getSessionOrInstanceZoneId());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -447,7 +447,8 @@ public class QJavalinImplementation
|
|||||||
context.cookie(SESSION_ID_COOKIE_NAME, session.getIdReference(), SESSION_COOKIE_AGE);
|
context.cookie(SESSION_ID_COOKIE_NAME, session.getIdReference(), SESSION_COOKIE_AGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUserTimezoneOffsetMinutesHeaderInSession(context, session);
|
setUserTimezoneOffsetMinutesInSession(context, session);
|
||||||
|
setUserTimezoneInSession(context, session);
|
||||||
}
|
}
|
||||||
catch(QAuthenticationException qae)
|
catch(QAuthenticationException qae)
|
||||||
{
|
{
|
||||||
@ -493,7 +494,7 @@ public class QJavalinImplementation
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private static void setUserTimezoneOffsetMinutesHeaderInSession(Context context, QSession session)
|
private static void setUserTimezoneOffsetMinutesInSession(Context context, QSession session)
|
||||||
{
|
{
|
||||||
String userTimezoneOffsetMinutes = context.header("X-QQQ-UserTimezoneOffsetMinutes");
|
String userTimezoneOffsetMinutes = context.header("X-QQQ-UserTimezoneOffsetMinutes");
|
||||||
if(StringUtils.hasContent(userTimezoneOffsetMinutes))
|
if(StringUtils.hasContent(userTimezoneOffsetMinutes))
|
||||||
@ -503,7 +504,7 @@ public class QJavalinImplementation
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// even though we're putting it in the session as a string, go through parse int, to make sure it's a valid int. //
|
// even though we're putting it in the session as a string, go through parse int, to make sure it's a valid int. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
session.setValue("UserTimezoneOffsetMinutes", String.valueOf(Integer.parseInt(userTimezoneOffsetMinutes)));
|
session.setValue(QSession.VALUE_KEY_USER_TIMEZONE_OFFSET_MINUTES, String.valueOf(Integer.parseInt(userTimezoneOffsetMinutes)));
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@ -514,6 +515,20 @@ public class QJavalinImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void setUserTimezoneInSession(Context context, QSession session)
|
||||||
|
{
|
||||||
|
String userTimezone = context.header("X-QQQ-UserTimezone");
|
||||||
|
if(StringUtils.hasContent(userTimezone))
|
||||||
|
{
|
||||||
|
session.setValue(QSession.VALUE_KEY_USER_TIMEZONE, userTimezone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
Reference in New Issue
Block a user