fix(platform): normalize legacy Vietnam timezone
This commit is contained in:
@@ -1,23 +1,43 @@
|
||||
package com.lab.labtimesheet;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
import com.lab.labtimesheet.config.SecurityProperties;
|
||||
|
||||
/** Application entry point and root component-scan boundary for Lab Timesheet. */
|
||||
/**
|
||||
* Application entry point and root component-scan boundary for Lab Timesheet.
|
||||
*
|
||||
* <p>The entry point also canonicalizes the legacy Windows Vietnam timezone alias before database
|
||||
* drivers inspect the JVM default timezone.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
public class LabtimesheetApplication {
|
||||
private static final String LEGACY_VIETNAM_TIME_ZONE = "Asia/Saigon";
|
||||
private static final String BUSINESS_TIME_ZONE = "Asia/Ho_Chi_Minh";
|
||||
|
||||
/**
|
||||
* Starts the standalone Spring Boot process.
|
||||
* Canonicalizes the process timezone and starts the standalone Spring Boot process.
|
||||
*
|
||||
* @param args command-line arguments forwarded to Spring Boot
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
normalizeDefaultTimeZone();
|
||||
SpringApplication.run(LabtimesheetApplication.class, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the legacy Windows Vietnam alias before pgJDBC sends it to PostgreSQL as a startup
|
||||
* parameter. Other supported system timezones remain unchanged.
|
||||
*/
|
||||
static void normalizeDefaultTimeZone() {
|
||||
if (LEGACY_VIETNAM_TIME_ZONE.equals(TimeZone.getDefault().getID())) {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(BUSINESS_TIME_ZONE));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.lab.labtimesheet;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.testcontainers.postgresql.PostgreSQLContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
class ApplicationTimeZoneIntegrationTest {
|
||||
|
||||
@Test
|
||||
void mainCanonicalizesLegacyAliasBeforeStartingSpring() {
|
||||
TimeZone originalTimeZone = TimeZone.getDefault();
|
||||
String[] args = {"--spring.profiles.active=test"};
|
||||
|
||||
try (MockedStatic<SpringApplication> springApplication = mockStatic(SpringApplication.class)) {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Saigon"));
|
||||
|
||||
LabtimesheetApplication.main(args);
|
||||
|
||||
assertThat(TimeZone.getDefault().getID()).isEqualTo("Asia/Ho_Chi_Minh");
|
||||
springApplication.verify(() -> SpringApplication.run(LabtimesheetApplication.class, args));
|
||||
} finally {
|
||||
TimeZone.setDefault(originalTimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void canonicalizesLegacyVietnamAliasBeforePostgresConnects() throws SQLException {
|
||||
TimeZone originalTimeZone = TimeZone.getDefault();
|
||||
|
||||
try (PostgreSQLContainer postgres =
|
||||
new PostgreSQLContainer(DockerImageName.parse("postgres:18.4"))) {
|
||||
postgres.start();
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Saigon"));
|
||||
|
||||
assertThat(TimeZone.getDefault().getID()).isEqualTo("Asia/Saigon");
|
||||
assertThatThrownBy(() -> openConnection(postgres))
|
||||
.isInstanceOf(SQLException.class)
|
||||
.hasMessageContaining("Asia/Saigon");
|
||||
|
||||
LabtimesheetApplication.normalizeDefaultTimeZone();
|
||||
|
||||
assertThat(TimeZone.getDefault().getID()).isEqualTo("Asia/Ho_Chi_Minh");
|
||||
try (Connection connection = openConnection(postgres)) {
|
||||
assertThat(connection.isValid(1)).isTrue();
|
||||
}
|
||||
} finally {
|
||||
TimeZone.setDefault(originalTimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void leavesSupportedSystemTimeZoneUnchanged() {
|
||||
TimeZone originalTimeZone = TimeZone.getDefault();
|
||||
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));
|
||||
|
||||
LabtimesheetApplication.normalizeDefaultTimeZone();
|
||||
|
||||
assertThat(TimeZone.getDefault().getID()).isEqualTo("Europe/Paris");
|
||||
} finally {
|
||||
TimeZone.setDefault(originalTimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
private static Connection openConnection(PostgreSQLContainer postgres) throws SQLException {
|
||||
return DriverManager.getConnection(postgres.getJdbcUrl(), postgres.getUsername(), postgres.getPassword());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user