Java时区国际化解决方案

国际化项目开发中关于时间的问题一 在上述代码中,我们生成了东八区晚上九点的时间,然后转换为时间戳,最后将这个时间戳转换为东十区的时间。时区转换1:时间是分时区的,如果把【时间戳】转【时间】,需要把时区加进去,同理,【时间】转【时间戳】时,也需要把时区加进去。时间与时区关系:时区决定了本地时间与UTC时间的偏移量。时间戳:不区分时区,表示自1970年1月1日00:00:00 UTC以来的秒数或毫秒数。时区转换2:将时间戳转换为可读时间时,需要考虑时区,以便正确显示本地时间。东八区时间: 2023-06-01 21:00:00 +0800。 阅读详情

在这里插入图片描述
当用户所在时区和服务器所在时区不一致时,会产生时区相关问题,如时间显示错误、程序取得的时间和数据库存储的时间不一致、定时任务的触发没有跟随用户当前的时区等等问题.

统一拦截时区

/**
 *
 **/
@Component
@Slf4j
public class TimeZoneIdInterceptor implements HandlerInterceptor {
    
    private static final String TIME_ZONE_CODE = "timeZoneCode";
    
    /**
     * 在控制器方法处理之前执行的预处理方法
     * <p>
     * 该方法用于在控制器方法执行前进行一些预处理操作,例如检查用户是否登录、记录日志等 如果该方法返回false,则表示不执行控制器方法;如果返回true,则表示继续执行控制器方法
     *
     * @param request  请求对象,用于获取请求信息
     * @param response 响应对象,用于向客户端发送响应
     * @param handler  控制器方法的对象,用于执行具体的控制器方法
     * @return 是否执行控制器的处理逻辑,true表示执行,false表示不执行
     * @throws Exception 如果发生异常,将抛出异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //获取TimeZoneId 默认东八区
        String timeZoneId=request.getHeader(TIME_ZONE_CODE);
        if(StringUtilsPlus.isBlank(timeZoneId)){
            timeZoneId = ZoneIdEnum.CTT.getZoneIdName();
        }
        TimeZoneIdContext.setTimeZoneId(timeZoneId);
        return true;
    }
    
    
    /**
     * controller方法执行后
     * <p>
     * 该方法主要用于在控制器方法处理完请求后进行一些额外的处理或清理工作 它是拦截器中的一部分,用于在请求被控制器处理后立即执行自定义逻辑
     *
     * @param request      请求对象,用于访问请求信息
     * @param response     响应对象,用于控制响应给客户端的信息
     * @param handler      被执行的控制器方法的引用,用于识别和可能操作控制器方法
     * @param modelAndView ModelAndView对象,包含要渲染的视图和模型数据
     * @throws Exception 如果在处理过程中发生异常,可以将其抛出
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        log.info("postHandle执行{}", modelAndView);
        TimeZoneIdContext.removeTimeZoneId();
    }
    
    
}

GET请求及POST表单请求(RequestParam和PathVariable参数):
自定义spring mvc的参数解析器,配置Converter<String, T>转换器实现参数转换

@Configuration
@Slf4j
public class DateConverterConfig {
    /**
     * 创建一个字符串到LocalDateTime的转换器
     *
     * 该方法通过定义一个Converter接口的匿名类来实现字符串到LocalDateTime的对象转换
     * 主要用于Spring框架中,以便在数据绑定、类型转换时使用
     *
     * @return Converter<String, LocalDateTime> 返回一个实现了Converter接口的匿名类实例,
     *         用于将字符串转换为LocalDateTime对象
     */
    @Bean
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                // String类型的日期字符串转为LocalDateTime类型,并加上时区处理
                // 如果源字符串不为空,则进行转换;否则返回null
                if(StringUtilsPlus.isNotBlank(source)){
                    return TimeZoneUtils.convertTimeZoneLocalDateTime(source, TimeZoneIdContext.getTimeZoneId().get(),
                            ZoneIdEnum.CTT.getZoneIdName());
                }
                return null;
            }
        };
    }
    
    /**
     * 创建一个字符串到日期的转换器
     *
     * 该方法通过定义一个Converter的Bean,实现了从字符串类型到Date类型的转换主要用于处理日期字符串,
     * 并考虑了时区的转换
     *
     * @return Converter<String, Date> 实现了从字符串到日期的转换功能
     */
    @Bean
    public Converter<String, Date> dateConverter() {
        return new Converter<String, Date>() {
            @Override
            public Date convert(String source) {
                // String类型的日期字符串转为LocalDateTime类型,并加上时区处理
                if(StringUtilsPlus.isNotBlank(source)){
                    return TimeZoneUtils.convertTimeZoneDate(source, TimeZoneIdContext.getTimeZoneId().get(),
                            ZoneIdEnum.CTT.getZoneIdName());
                }
                return null;
            }
        };
    }
}

  1. POST-application/json请求(RequestBody参数)在使用javabean作为入参时,javabean对象中的Date、LocalDateTime类型可以根据请求头中的时区字段自动转为应用服务当前时区的时间
  2. 接口返回对象时,对象中的Date、LocalDateTime类型的日期值,可以根据请求头中的时区字段,自动转为该时区的时间
@JsonComponent
public class DateJsonSerializerConfig {
    /**
     * 反序列化,其它时区的时间转为本地时间
     */
    public static class LocalDateTimeJsonDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            // 根据时区字段将日期转为本地时区时间
            // String类型日期转为LocalDateTime类型
            String timeZone = StringUtilsPlus.defaultIfEmpty(TimeZoneIdContext.getTimeZoneId().get(), ZoneIdEnum.CTT.getZoneIdName());
            String value  = jsonParser.getValueAsString();
            if(StringUtilsPlus.isNotBlank(value)){
                return TimeZoneUtils.convertTimeZoneLocalDateTime(value,timeZone,ZoneIdEnum.CTT.getZoneIdName());
            }
            return null;
        }
    }
    /**
     * 序列化,本地时间转为其它时区的时间
     */
    public static class LocalDateTimeJsonSerializer extends JsonSerializer<LocalDateTime> {
        
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator,
                SerializerProvider serializerProvider) throws IOException {
            //  本地时间转对应时区的时间
            String timeZone = StringUtilsPlus.defaultIfEmpty(TimeZoneIdContext.getTimeZoneId().get(), ZoneIdEnum.CTT.getZoneIdName());
            if(localDateTime!=null) {
                jsonGenerator.writeString(TimeZoneUtils.convertTimeZoneLocalDateTime(localDateTime, timeZone).format(
                        DateTimeFormatter.ofPattern(GlobalConstants.YYYY_MM_DD_HH_MM_SS)));
            }
        }
    }
    
    
    /**
     * 反序列化,其它时区的时间转为本地时间
     */
    public static class DateTimeJsonDeserializer extends JsonDeserializer<Date> {
        @Override
        public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            // 根据时区字段将日期转为本地时区时间
            // String类型日期转为LocalDateTime类型
            String timeZone = StringUtilsPlus.defaultIfEmpty(TimeZoneIdContext.getTimeZoneId().get(), ZoneIdEnum.CTT.getZoneIdName());
            String value  = jsonParser.getValueAsString();
            if(StringUtilsPlus.isNotBlank(value)){
                return TimeZoneUtils.convertTimeZoneDate(value,timeZone,ZoneIdEnum.CTT.getZoneIdName());
            }
            return null;
        }
    }
    /**
     * 序列化,本地时间转为其它时区的时间
     */
    public static class DateTimeJsonSerializer extends JsonSerializer<Date> {
        
        @Override
        public void serialize(Date date, JsonGenerator jsonGenerator,
                SerializerProvider serializerProvider) throws IOException {
            //  本地时间转对应时区的时间
            String timeZone = StringUtilsPlus.defaultIfEmpty(TimeZoneIdContext.getTimeZoneId().get(), ZoneIdEnum.CTT.getZoneIdName());
            if(date!=null) {
                jsonGenerator.writeString(DateUtil.format(TimeZoneUtils.convertTimeZoneDate(date, timeZone),
                        GlobalConstants.YYYY_MM_DD_HH_MM_SS));
            }
        }
    }
}

时间时区相互转化工具类

/**
 * 时间时区转化
 **/
public class TimeZoneUtils {
    
    /***
     * 时间转化
     * 将给定的日期对象从一个时区转换到另一个时区
     * @param date 需要转换的日期对象
     * @param timeZone 目标时区
     * @return 转换后的日期对象,如果目标时区与默认时区相同,则返回原始日期对象
     */
    public static Date convertTimeZoneDate(Date date, String timeZone) {
        // 检查目标时区是否为默认时区,如果是,则无需转换,直接返回原始日期
        if (isDefaultTimeZone(timeZone)) {
            return date;
        }
        // 获取目标时区
        TimeZone otherZone = TimeZone.getTimeZone(timeZone);
        // 创建SimpleDateFormat对象,用于日期的格式化和解析
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 设置SimpleDateFormat的时区为其他时区
        sdf.setTimeZone(otherZone);
        // 用于存储转换后的日期对象
        Date otherZoneDate = null;
        try {
            // 将格式化后的日期字符串解析为日期对象,该对象现在处于目标时区
            // 使用纽约时区格式化日期
            String dateInNewYork = sdf.format(date);
            otherZoneDate = DateUtil.parse(dateInNewYork,"yyyy-MM-dd HH:mm:ss");
        } catch (Exception e) {
            // 如果发生异常,打印异常信息
            e.printStackTrace();
        }
        // 返回转换后的日期对象
        return otherZoneDate;
    }
    
    /**
     * 将LocalDate对象转换为特定时区的LocalDate对象 此方法主要用于在处理不同时区的日期时进行转换,以确保日期的正确解析和表示
     *
     * @param localDate 输入的LocalDate对象,表示日期
     * @param timeZone  目标时区的字符串表示,如"America/New_York"
     * @return 转换后特定时区的LocalDate对象
     */
    public static LocalDate convertTimeZoneLocalDate(LocalDate localDate, String timeZone) {
        if (isDefaultTimeZone(timeZone)) {
            return localDate;
        }
        // 指定时区
        ZoneId zoneId = ZoneId.of(timeZone);
        // 将LocalDate转换为指定时区的ZonedDateTime 该时区一天的开始时刻的
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(zoneId);
        // 返回转换后的LocalDate对象
        return zonedDateTime.toLocalDate();
    }
    /**
     * 将给定的时间字符串从一个时区转换到另一个时区
     * 此方法首先将时间字符串解析为本地日期时间对象,然后将其转换到源时区,
     * 最后将时间转换到目标时区,保持时间点不变
     *
     * @param dateTimeString 时间字符串,表示源时区中的本地日期和时间
     * @param sourceTimeZone   源时区的ID,例如"America/New_York"
     * @param targetTimeZone   目标时区的ID,例如"Europe/London"
     * @return 转换到目标时区后的本地日期时间对象
     */
    public static LocalDateTime convertTimeZoneLocalDateTime(String dateTimeString,String sourceTimeZone,String targetTimeZone) {
        // 获取源时区的ZoneId对象
        ZoneId sourceZoneId = ZoneId.of(sourceTimeZone);
        // 获取目标时区的ZoneId对象
        ZoneId targetZoneId = ZoneId.of(targetTimeZone);
        // 创建DateTimeFormatter指定日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(sourceZoneId);
        // 解析字符串到ZonedDateTime
        ZonedDateTime zonedDateTimeSource = ZonedDateTime.parse(dateTimeString, formatter);
        // 转换到另一个时区
        ZonedDateTime zonedDateTimeTarget = zonedDateTimeSource.withZoneSameInstant(targetZoneId);
        // 将源时区应用到本地日期时间,并转换到目标时区,最后返回转换后的本地日期时间
        return zonedDateTimeTarget.toLocalDateTime();
    }
    
    /**
     * 转换日期时间字符串从一个时区到另一个时区
     * 此方法首先根据源时区解析输入的日期时间字符串,然后将其转换到目标时区
     * 最后返回转换后的日期时间的Date对象
     *
     * @param dateTimeString 日期时间字符串,格式为"yyyy-MM-dd HH:mm:ss"
     * @param sourceTimeZone 源时区ID,如"Asia/Shanghai"
     * @param targetTimeZone 目标时区ID,如"America/New_York"
     * @return 转换时区后的日期时间对象
     */
    public static Date convertTimeZoneDate(String dateTimeString,String sourceTimeZone,String targetTimeZone) {
        // 获取源时区的ZoneId对象
        ZoneId sourceZoneId = ZoneId.of(sourceTimeZone);
        // 获取目标时区的ZoneId对象
        ZoneId targetZoneId = ZoneId.of(targetTimeZone);
        // 创建DateTimeFormatter指定日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(sourceZoneId);
        // 解析字符串到ZonedDateTime
        ZonedDateTime zonedDateTimeSource = ZonedDateTime.parse(dateTimeString, formatter);
        // 转换到另一个时区
        ZonedDateTime zonedDateTimeTarget = zonedDateTimeSource.withZoneSameInstant(targetZoneId);
        // 将源时区应用到本地日期时间,并转换到目标时区,最后返回转换后的本地日期时间
        LocalDateTime targetLocalDateTime = zonedDateTimeTarget.toLocalDateTime();
        Date date = Date.from(targetLocalDateTime.atZone(targetZoneId).toInstant());
        return date;
    }
    /**
     * 将LocalDateTime对象从默认时区转换到指定时区
     *
     * @param localDateTime 需要转换的LocalDateTime对象
     * @param timeZone      目标时区的ID字符串
     * @return 转换后的LocalDateTime对象
     */
    public static LocalDateTime convertTimeZoneLocalDateTime(LocalDateTime localDateTime, String timeZone) {
        if (isDefaultTimeZone(timeZone)) {
            return localDateTime;
        }
        // 默认时区
        ZoneId sourceZoneId = currentZoneId();
        ZonedDateTime sourceZonedDateTime = localDateTime.atZone(sourceZoneId);
        // 新时区
        ZoneId targetZoneId = ZoneId.of(timeZone);
        ZonedDateTime targetZonedDateTime = sourceZonedDateTime.withZoneSameInstant(targetZoneId);
        // 时区转换
        return targetZonedDateTime.toLocalDateTime();
    }
    
    /**
     * 是否是默认时区
     *
     * @param timeZone
     * @return
     */
    public static boolean isDefaultTimeZone(String timeZone) {
        return StringUtilsPlus.isBlank(timeZone) || currentZoneId().getId().toUpperCase()
                .equals(timeZone.toUpperCase());
    }
    
    /**
     * 指定默认时区
     *
     * @return java.time.ZoneId 返回指定的时区ID
     */
    public static ZoneId specifyDefaultZone() {
        // 创建一个时区ID对象,指定时区为中国的北京时间
        ZoneId zoneId = ZoneId.of(ZoneIdEnum.CTT.getZoneIdName());
        // 返回创建的时区ID对象
        return zoneId;
    }
    
    /**
     * 获取当前系统的时区ID
     * <p>
     * 此方法用于识别和返回系统默认的时区ID它在需要时区信息来处理日期和时间的场景中特别有用
     *
     * @return ZoneId 当前系统的时区ID
     */
    public static ZoneId currentZoneId() {
        // 获取系统默认时区的时区ID
        ZoneId systemDefaultZone = ZoneId.systemDefault();
        return systemDefaultZone;
    }
    
    /**
     * 指定时区获取当前日期
     * 此方法主要解决在不同地区运行代码时获取的日期不一致的问题
     * 通过指定默认时区,确保在任何地方运行都能获取到正确的日期
     *
     * @return 返回指定时区的当前日期
     */
    public static LocalDate specifyTimeZoneLocalDate() {
        return LocalDate.now(specifyDefaultZone());
    }
    /**
     * 获取指定时区的当前日期和时间
     * 此方法通过指定默认时区来获取当前的日期和时间,主要用于需要考虑时区的因素以确保时间一致性的场景
     *
     * @return 返回指定时区的当前日期和时间
     */
    public static LocalDateTime specifyTimeZoneLocalTimeDate() {
        return LocalDateTime.now(specifyDefaultZone());
    }
    
    
    /**
     * 获取  亚洲/上海 当前时间
     *
     * 此方法旨在提供一个简单的方式来获取当前时间,并将其转换为CTT时区的时间
     * 它使用了更通用的convertTimeZoneLocalDateTime方法来执行实际的时区转换
     *
     * @return 当前时间转换为CTT时区后的LocalDateTime
     */
    public static LocalDateTime cttLocalDateTime() {
        return convertTimeZoneLocalDateTime(LocalDateTime.now(), ZoneIdEnum.CTT.getZoneIdName());
    }
}

public class TimeZoneIdContext {
    
    private static final ThreadLocal<String> TIME_ZONE_ID = new ThreadLocal<>();
    
    public static void setTimeZoneId(String timeZoneId) {
        TIME_ZONE_ID.set(timeZoneId);
    }
    
    public static ThreadLocal<String> getTimeZoneId() {
        return TIME_ZONE_ID;
    }
    
    public static void removeTimeZoneId() {
        TIME_ZONE_ID.remove();
    }
    
    /**
     * 获取时区id 如果为空则返回默认时区id
     *
     * @return
     */
    public static String get() {
        String zoneId = TIME_ZONE_ID.get();
        if (StringUtils.isEmpty(zoneId)) {
            return ZoneIdEnum.CTT.getZoneIdName();
        }
        return zoneId;
    }
}

public enum ZoneIdEnum {
    
    /**
     * "Australia/Darwin","澳洲/达尔文"
     */
    ACT("Australia/Darwin", "澳洲/达尔文"),
    
    /**
     * "Australia/Sydney","澳洲/悉尼"
     */
    AET("Australia/Sydney", "澳洲/悉尼"),
    
    /**
     * "America/Argentina/Buenos_Aires","美洲/阿根廷/布宜诺斯艾利斯"
     */
    AGT("America/Argentina/Buenos_Aires", "美洲/阿根廷/布宜诺斯艾利斯"),
    
    /**
     * "Africa/Cairo","非洲/开罗"
     */
    ART("Africa/Cairo", "非洲/开罗"),
    
    /**
     * "America/Anchorage","美洲/安克雷奇"
     */
    AST("America/Anchorage", "美洲/安克雷奇"),
    
    /**
     * "America/Sao_Paulo","美洲/圣保罗"
     */
    BET("America/Sao_Paulo", "美洲/圣保罗"),
    /**
     * "Asia/Dhaka","亚洲/达卡"
     */
    BST("Asia/Dhaka", "亚洲/达卡"),
    
    /**
     * "Africa/Harare","非洲/哈拉雷"
     */
    CAT("Africa/Harare", "非洲/哈拉雷"),
    
    /**
     * "America/St_Johns","美洲/圣约翰"
     */
    CNT("America/St_Johns", "美洲/圣约翰"),
    
    /**
     * "America/Chicago","美洲/芝加哥"
     */
    CST("America/Chicago", "美洲/芝加哥"),
    
    /**
     * "Asia/Shanghai","亚洲/上海"
     */
    CTT("Asia/Shanghai", "亚洲/上海"),
    
    /**
     * "Africa/Addis_Ababa","非洲/亚的斯亚贝巴"
     */
    EAT("Africa/Addis_Ababa", "非洲/亚的斯亚贝巴"),
    
    /**
     * "Europe/Paris","欧洲/巴黎"
     */
    ECT("Europe/Paris", "欧洲/巴黎"),
    
    /**
     * "America/Indiana/Indianapolis","美洲/印第安纳州/印第安纳波利斯"
     */
    IET("America/Indiana/Indianapolis", "美洲/印第安纳州/印第安纳波利斯"),
    
    /**
     * "Asia/Kolkata","亚洲/加尔各答"
     */
    IST("Asia/Kolkata", "亚洲/加尔各答"),
    
    /**
     * "Asia/Tokyo","亚洲/东京"
     */
    JST("Asia/Tokyo", "亚洲/东京"),
    
    /**
     * "Pacific/Apia","太平洋/阿皮亚"
     */
    MIT("Pacific/Apia", "太平洋/阿皮亚"),
    
    /**
     * "Asia/Yerevan","亚洲/埃里温"
     */
    NET("Asia/Yerevan", "亚洲/埃里温"),
    
    /**
     * "Pacific/Auckland","太平洋/奥克兰"
     */
    NST("Pacific/Auckland", "太平洋/奥克兰"),
    
    /**
     * "Asia/Karachi","亚洲/卡拉奇"
     */
    PLT("Asia/Karachi", "亚洲/卡拉奇"),
    
    /**
     * "America/Phoenix","美洲/凤凰城"
     */
    PNT("America/Phoenix", "美洲/凤凰城"),
    
    /**
     * "America/Puerto_Rico","美洲/波多黎各"
     */
    PRT("America/Puerto_Rico", "美洲/波多黎各"),
    
    /**
     * "America/Los_Angeles","美洲/洛杉矶"
     */
    PST("America/Los_Angeles", "美洲/洛杉矶"),
    
    /**
     * "Pacific/Guadalcanal","太平洋/瓜达尔卡纳尔岛"
     */
    SST("Pacific/Guadalcanal", "太平洋/瓜达尔卡纳尔岛"),
    
    /**
     * "Asia/Ho_Chi_Minh","亚洲/胡志明市"
     */
    VST("Asia/Ho_Chi_Minh", "亚洲/胡志明市"),
    
    /**
     * "-05:00","东部标准时间"(纽约、华盛顿)
     */
    EST("-05:00", "东部标准时间"),
    
    /**
     * "-07:00","山地标准时间"
     */
    MST("-07:00", "山地标准时间"),
    
    /**
     * "-10:00","夏威夷-阿留申标准时区"
     */
    HST("-10:00", "夏威夷-阿留申标准时区"),;
    
    private final String zoneIdName;
    private final String zoneIdNameCn;
    
    public String getZoneIdName() {
        return zoneIdName;
    }
    
    public String getZoneIdNameCn() {
        return zoneIdNameCn;
    }
    
    ZoneIdEnum(String zoneIdName, String zoneIdNameCn) {
        this.zoneIdName = zoneIdName;
        this.zoneIdNameCn = zoneIdNameCn;
    }
}

参考:链接

SpringBoot时区问题解决,彻底解决时差问题 第一步:确认docker时区 进入容器中 docker exec -it 容器name bash 查看容器时区: date 第二步确认数据库时区 SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP); 如果显示的是08:00:00则是cst时区。 如果不是cst时区,则执行Sql: set global time_zone = '+8:00'; ##修改mysql全局时区为北京时间,即我们所在的东8区 set time_zone = '+8:00'; . 阅读详情

相关推荐

Java日期处理:DateFormat与SimpleDateFormat实战指南

日期处理是软件开发中的基础但关键的技术点,涉及时间数据的格式化、解析与时区转换等核心操作。Java提供了DateFormat及其实现类SimpleDateFormat来处理日期字符串的转换,这些工具类通过格式模式字符串定义输出样式,同时需要考虑时区和本地化配置。在实际工程中,日期处理的线程安全问题尤为突出,SimpleDateFormat的非线程安全特性可能导致多线程环境下的数据混乱。针对这一问题,可以采用ThreadLocal缓存或升级到Java 8的DateTimeFormatter等解决方案。在Web

weixin_28717969的博客 175

Java 时区国际化处理

项目主打海外业务,不可避免碰到时区的问题。目前的解决方案是,服务器、数据库统一设置为0时区,前端提交日期格式的字符串参数,请求头传递时区的参数(如:东八区【+8】,西一区【-1】),后台根据偏移量将日期字符串转换成0时区的Date。

SpringHASh的博客 1780

避坑指南:EasyExcel导入导出时你可能遇到的6个坑(附Converter完整解决方案)

本文深入解析EasyExcel在Java Excel导入导出中的6个常见问题,包括数据映射、日期格式化、多工作表导出性能优化等,并提供完整的Converter解决方案。特别针对模板导出和动态表头等企业级需求,给出可直接落地的代码示例,帮助开发者高效避坑。

weixin_29258297的博客 316

Java国际化时区时间数据问题排查总结

Java国际化时区时间数据问题排查总结

handsomestWei的博客 593

专为Android优化的Joda-Time日期处理库实战应用

/ ISO 标准输出// 中文友好型DateTimeFormatter chineseFormat = DateTimeFormat.forPattern("yyyy年MM月dd日 HH:mm");Joda-Time for Android 不仅仅是一个时间库的替代品,它是对“如何正确建模时间”这一工程问题的深刻回答。它用不可变性解决了并发安全,用语义化 API 提升了可读性,用丰富的功能覆盖了复杂场景,同时在性能和兼容性上做出了优秀平衡。尽管 Java 8 的java.time。

weixin_42601702的博客 686

java国际化&时间处理

NULL 博文链接:https://hoochiang.iteye.com/blog/1848534

揭秘Docker容器时区混乱难题:3步搞定ICU国际化支持

轻松解决Docker容器时区混乱问题,掌握时区与本地化配置(ICU 库集成)三大核心步骤。适用于多语言环境部署,实现精准时间显示与国际化支持,提升应用兼容性与用户体验,值得收藏。

Algorhythm的博客 801

“挑战杯”大赛“揭榜挂帅”赛道-baseline解析

在这个脚本中,txt文件的保存路径为'yolov7/datasets/Fatigue_driving_detection/txt_labels/',而xml文件的路径为'./label_xml/'。标注图片后的产物是会给每一个图片对应生成一个xml格式的文件,但是如果要用yolo框架去训练模型,输入的数据必须是txt格式,因此这里有一步转换格式的过程。注意看:obs这里有三个文件夹,第一个是关键帧的文件夹A,第二个是标注时输出的位置为文件夹B,第三个是智能标注后和手动标注的合集文件夹C。

m0_62899814的博客 2321

国际化标签2

国际化标签 一 动态文件的概念 1.什么时候使用动态文本 如果字符串中包含了多个与国际化相关的数据,可以使用MessageFormat类对这些数据进行批量处理 ----比如一段字符串中包含时间、数字、货币、、可以进行批量处理 2.如何使用动态文本---批量处理 (1)MessageFormat类允许开发人员用占位符替换掉字符串中的敏感数据(即国际化相关的数据)。 (2)Messag

xiaolang827的专栏 352

HALCON卡尺模型实战:5分钟搞定工件尺寸测量(附完整代码)

本文详细介绍了HALCON卡尺模型在工件尺寸测量中的实战应用,通过5分钟快速搭建测量系统的完整指南,包括基础配置、高级参数调优和完整代码示例。卡尺模型能自动识别边缘并计算精确尺寸,显著提升工业视觉检测的效率和一致性,特别适用于实时测量场景。

weixin_42570296的博客 460

OpenHarmony v4.1 Release设置应用随系统自动启动

OpenHarmony 4.1 版本中的 Ability Manager Service (AMS) 提供了应用自启动管理功能,允许系统控制哪些应用可以在系统启动时自动运行。这需要以下两个主要步骤:启用系统的自启动管理支持开发一个系统应用来管理自启动配置。

afufufufu的博客 1898

alpine linux中文乱码,alpine jdk 中文乱码

一、概述使用alpine镜像构建了一个oracle jdk的镜像,运行java业务时,查看日志,显示中文乱码。但是,基于Alpine Linux的Docker基础镜像的镜像文件很小,也有代价:把glibc替换为了musl libc,但是musl libc不支持国际化和本地化, 所以你想显示中文,还得安装glibc把bash替换为了ash,但是ash不支持数组特性, 但是,我们大多数已经写好的脚本,...

weixin_35349247的博客 1520

自相关互相关卷积的_相关性(Correlation)和相干性(Coherence)

1. 概念相关性(Correlation,或称相关系数或关联系数),显示两相关变量之间线性关系的强度和方向。在统计学中,相关的意义是用来衡量两个变量相对于其相互独立的距离。相干性(Coherence),与相关性计算得到的信息非常相似,都是衡量两个变量之间的相关程度,只是相干性多用于频域计算,可以在基于频率上给出更多的信息,而相关性多用于普通的数组计算和时域信号。这里其实应该有三个概念,c...

weixin_39963053的博客 3332

Servlet 处理日期

在Servlet中处理日期需要熟悉和类。你可以使用这些类来获取当前日期、格式化日期字符串、解析日期字符串,并考虑国际化和时区问题。通过这些技术,你可以在Servlet中有效地处理日期和时间数据。

lsx202406的博客 313

不止于使能:用汇川PLC功能块封装,实现伺服轴状态管理与安全逻辑

本文深入探讨了汇川PLC功能块封装在伺服轴控中的应用,详细介绍了如何通过高级封装技术实现伺服轴的状态管理与安全逻辑。文章涵盖了从基础使能到全生命周期监控的进化,多轴协同的实例化管理策略,以及安全逻辑的防御性编程技巧,为工业自动化领域的工程师提供了实用的解决方案和最佳实践。

weixin_28684825的博客 271

【linux】linux 出现一个网卡绑定多个ip怎么处理

我的原因是我使用了dhcp,这个会自动分配ip, 将 BOOTPROTO 参数由 dhcp 改为 static,并移除或注释掉与动态分配地址 10.0.2.15 相关的配置行(如果存在)。执行后,您可以再次使用 ip -4 a 或 ifconfig 命令确认 IP 地址已被移除。输出可以看出,您的虚拟机(k8s003)中存在一个名为 enp0s3 的网卡绑定了多个 IPv4 地址。对于某些 Linux 发行版(如 Ubuntu、Debian),您可能需要编辑网络接口的配置文件来移除多余的 IP 地址。

九师兄 297

Day3|国际化框架中的“时区大坑”——那些年我被时间折磨的日子

【摘要】文章深入剖析了国际化项目中的时区问题,指出时间戳存储、时区转换各环节的常见误区。通过实际案例展示了前端传递时间戳后,因后端偏移处理、环境配置不一致(服务器/JVM/数据库时区不统一)及工具显示差异导致的数据混乱问题。提出解决方案:规范使用UTC时间戳、统一环境时区配置、明确可视化工具设置,并强调时间戳存储应避免偏移处理,仅在展示层进行本地化转换。最后给出关键建议:全链路采用统一时间标准,严格定义接口规范,实现跨时区业务的可靠时间管理。

chenglexiang的博客 952

思维链:让AI更接近人类思维的技术

本文将探讨一种名为“思维链”的技术,它旨在让AI更接近人类思维。文章首先介绍了问题背景与核心概念,接着讲解了算法原理和数学模型,随后阐述了系统分析与架构设计,最后通过项目实战展示了思维链的实际应用,并提供了最佳实践和小结。思维链是一种旨在模拟人类思维过程的技术,它通过构建一系列相互关联的思维方式,实现对复杂问题的分析和解决。思维链算法是一种基于人类思维过程的人工智能算法,它通过构建一系列思维链,实现对问题的分析和解决。智能问答系统是一种常见的人工智能应用,它能够回答用户提出的各种问题。

AI天才研究院 942

ICU4J开发环境配置:Eclipse终极搭建指南

ICU4J是一款强大的国际化组件库,为Java应用提供全面的Unicode支持和本地化功能。本指南将带你快速完成ICU4J开发环境的搭建,让你轻松开启国际化应用开发之旅。 ## 准备工作:环境要求 在开始配置前,请确保你的开发环境满足以下要求: - JDK 8或更高版本 - Eclipse IDE 2020-06或更高版本 - Maven 3.6.x - Git工具 ## 第一步:获取ICU

gitblog_00967的博客 375

嵌入式工程师成长之路(1)——元件基础(试读版)

上拉电阻阻值选错导致MCU反复重启?0欧电阻竟然能“背锅”信号干扰?高精密采样电阻的温漂毁了整个控制系统?——这些问题,都是基础不牢!优快云硬件领域头部博主十年经验汇总,涵盖电阻分类、封装、实战选型、避坑指南,附带职业进阶路径,助你从小白进阶为“电路医生”!

云轩阁 34万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

27/Feb/2008:10:12:44 +0800这样的日期格式在java里的解析

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; /* * * @author zhousheng * @version 2013-1-17 */ public class Dat...

zhousheng193的专栏 648

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java国际化之时区问题处理

原文:https://moon-walker.iteye.com/blog/2396035 在国际化的项目中需要处理的日期时间问题主要有两点: 1、日期时间的国际化格式问题处理; 2、日期时间的时区问题处理,这两个问题要区分开,不要弄混了。 日期时间国际化化格式处理 对应的关键词:Locale 日期时间的国际化格式指的是在不同的国家和地区对日期时间的显示方式...

dgqvhtlwq472235338的博客 743

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

JAVA国际版答题系统练习模拟考试系统的开发难点

本文探讨了开发JAVA国际版答题系统的主要技术挑战及解决方案。系统面临多语言支持、高并发处理、防作弊机制、复杂题型适配、数据分析和跨时区管理等核心难题。针对这些问题,文章提出了采用Spring国际化实现多语言切换、Redis缓存和异步处理应对高并发、前端监控和设备指纹识别防止作弊、策略模式实现多样化判分、Flink进行实时数据分析等技术方案。推荐使用SpringBoot3+WebFlux+Redis+Flink等技术栈,结合Docker容器化和Kubernetes部署,构建高性能、安全可靠的多语言考试系统。

小马总的博客 368

Java Bean验证避坑指南:javax.validation.constraints注解的10个常见错误用法

本文详细解析了Java开发中使用javax.validation.constraints注解进行Bean验证时的10个常见错误用法,包括注解组合冲突、时间验证陷阱、国际化缺陷等关键问题。通过实际代码示例和最佳实践对比,帮助开发者避免验证漏洞,提升代码健壮性和系统性能。

weixin_29258297的博客 402

Java字符串格式化输出详解与最佳实践

字符串格式化是编程中的基础技术,通过预定义模板动态插入变量实现标准化输出。其核心原理是将数字、日期等数据类型按照指定格式转换为字符串,确保输出的一致性和可读性。在Java中,String.format()和Formatter类提供了强大的格式化能力,而MessageFormat则支持国际化需求。合理使用格式化技术能显著提升日志可读性、报表生成效率,特别是在金融计算、多语言支持等场景中体现关键价值。对于高频调用的场景,预编译Formatter实例或使用StringBuilder能有效优化性能。掌握Java字符

weixin_32430941的博客 281
上一篇: spring boot 深入多层实体参数参数进一步校验
下一篇: localdatetime获取本周、上周、本月、上月、本季度、上季度、本年、去年工具类
狂野弘仁
博客等级 码龄8年 34粉丝 81原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值