解决前端存入时间和从数据库读取时间不一致

这个问题根本上是前端时区和数据库时区不一致导致的,最简单的方式就是把db的链接手动设置时区,这样的话就可以解决时区问题,但是这样还有一个问题.如果用户不在你的时区登录你的系统的话,这样的解决方式就失效了,接下来我就会给出一个完美的答案,因为公司的db链接规定的是新加坡,而我在中国,测试必出现问题,所以想到了下面的解决方案.

Front-End

首先是前端的处理,我是用的是angular,使用的是TypeScript

 private convert(holiday: Holiday): Holiday {
    holiday.fromDate = new Date(holiday.fromDate.getTime() + Math.abs(new Date().getTimezoneOffset()) * 60 * 1000);
    holiday.toDate = new Date(holiday.toDate.getTime() + Math.abs(new Date().getTimezoneOffset()) * 60 * 1000);
    const copy: Holiday = Object.assign({}, holiday);
    return copy;
  }

这段代码是重要的转换代码,因为从前端取到的时间都是带有时区的,这时候我们手动把这个带有时区的时间转换成UTC,也就是国际标准时间,从而消除了时区的影响,这时候只需要在call back-end api 的时候call一下这个方法

create(holiday: Holiday): Observable<Holiday> {
    const copy = this.convert(holiday);
    return this.http.post(this.holidayAdminUrl, copy).pipe(
      map((res: any) => {
        const jsonResponse = res.body;
        this.convertItemFromServer(jsonResponse);
        return jsonResponse;
      })
    );
  }

就可以了.

Back-End

其实后端的code都差不多,但是有一个问题必须要注意,使用的时间类型必须是包含时分秒的,不能是例如LocalDate这种类型,因为这种只包含日月年,这样就会导致我们前端对时区的处理完全失效了.我个人使用的是Timestamp,做逻辑处理的时候再转成Calendar来处理.

Enhance

使用 ZonedDateTime, 可以看我另外一篇blog.

前端传过来之后用 ZonedDateTime转成UTC进行存储.

Enhance2

或者后端使用Instant作为字段类型,前端传入用toJSON(),这样就不会有时区问题了

 	@Column(name = "start_dt")
    private Instant startDt;

    @Column(name = "end_dt")
    private Instant endDt;
 protected convertDateFromClient(record: IRecord): IRecord {
    const copy: IRecord = Object.assign({}, record, {
      startDt: record.startDt && record.startDt.isValid() ? record.startDt.toJSON() : undefined,
      endDt: record.endDt && record.endDt.isValid() ? record.endDt.toJSON() : undefined,
    });
    return copy;
  }

前端接收的时候用moment把Date String 转换成moment就可以了.

//"moment": "2.27.0",

import * as moment from 'moment';

 query(req?: any): Observable<EntityArrayResponseType> {
    const options = createRequestOption(req);
    return this.http
      .get<IRecord[]>(this.resourceUrl, { params: options, observe: 'response' })
      .pipe(map((res: EntityArrayResponseType) => this.convertDateArrayFromServer(res)));
  }

protected convertDateArrayFromServer(res: EntityArrayResponseType): EntityArrayResponseType {
    if (res.body) {
      res.body.forEach((record: IRecord) => {
        record.startDt = record.startDt ? moment(record.startDt) : undefined;
        record.endDt = record.endDt ? moment(record.endDt) : undefined;
      });
    }
    return res;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,您需要定义一个包含图片数据的实体类,并使用JPA注解将其映射到数据库的一张表。例如,以下是一个包含图片数据的实体类的示例: ```java @Entity @Table(name = "image") public class ImageEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @Lob private byte[] data; // getters and setters } ``` 其,`data` 属性使用了 `@Lob` 注解,表示将其映射为数据库的大对象类型。 接下来,在Spring Boot定义一个RESTful的API,用于接收前端上传的图片数据,并将其存储到数据库。例如: ```java @RestController @RequestMapping("/api/images") public class ImageController { @Autowired private ImageRepository imageRepository; @PostMapping("/upload") public ResponseEntity<?> uploadImage(@RequestParam("file") MultipartFile file) { try { ImageEntity imageEntity = new ImageEntity(); imageEntity.setName(file.getOriginalFilename()); imageEntity.setData(file.getBytes()); imageRepository.save(imageEntity); return ResponseEntity.ok().build(); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("Failed to upload image"); } } @GetMapping("/{id}") public ResponseEntity<byte[]> getImage(@PathVariable("id") Long id) { Optional<ImageEntity> optional = imageRepository.findById(id); if (optional.isPresent()) { ImageEntity imageEntity = optional.get(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.IMAGE_JPEG); return new ResponseEntity<>(imageEntity.getData(), headers, HttpStatus.OK); } else { return ResponseEntity.notFound().build(); } } } ``` 其,`uploadImage` 方法用于接收前端上传的图片数据,并将其存储到数据库;`getImage` 方法用于根据图片的ID从数据库读取图片数据,并返回给前端。 最后,在Vue前端使用 `axios` 或其他HTTP库发送请求,上传图片并显示。例如: ```vue <template> <div> <input type="file" @change="uploadImage"> <img :src="imageUrl" v-if="imageUrl"> </div> </template> <script> import axios from 'axios'; export default { data() { return { imageUrl: null }; }, methods: { uploadImage(event) { const file = event.target.files[0]; const formData = new FormData(); formData.append('file', file); axios.post('/api/images/upload', formData) .then(() => this.fetchImage()) .catch(error => console.error(error)); }, fetchImage() { axios.get(`/api/images/${id}`, { responseType: 'arraybuffer' }) .then(response => { const imageUrl = URL.createObjectURL(new Blob([response.data], { type: 'image/jpeg' })); this.imageUrl = imageUrl; }) .catch(error => console.error(error)); } } }; </script> ``` 其,`uploadImage` 方法用于上传图片数据;`fetchImage` 方法用于根据图片的ID从后端获取图片数据,并使用 `Blob` 对象将其转换为URL,以便在 `<img>` 标签显示
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值