如何解码 Flutter iso8601 DateTime to Go Api RFC3339 pgtype.Date 和 pgtype.Timestamptz

How to decode Flutter iso8601 DateTime to Go Api RFC3339 pgtype.Date and pgtype.Timestamptz

在我的 Go API 中,我正在尝试使用 json 解码来解析以下 json.

{"contract_id":0,"date_established":"2022-04-03T00:00:00.000","expiry_date":null,"extension_expiry_date":null,"description":"fffff"}

我得到一个错误:

parsing time "\"2022-04-03T00:00:00.000\"" as "\"2006-01-02T15:04:05Z07:00\"": cannot parse "\"" as "Z07:00"

我该如何解决这个错误?

这是我的结构:

// Contract model
type Contract struct {
    ContractId          *int       `json:"contract_id"`
    CompanyId           *int       `json:"company_id"`
    DateEstablished     *time.Time `json:"date_established"`
    ExpiryDate          *time.Time `json:"expiry_date"`
    ExtensionExpiryDate *time.Time `json:"extension_expiry_date"`
    Description         *string    `json:"description"`
}

这是我的代码:

func (rs *appResource) contractCreate(w http.ResponseWriter, r *http.Request) {

    var contract Contract

    decoder := json.NewDecoder(r.Body)

    err = decoder.Decode(&contract)

Go 使用 RFC 3339 编码时间,如果你控制正在生成的 json 你只需要将 2022-04-03T00:00:00.000 更改为 2022-04-03T00:00:00.000Z

例如这行得通。

type Contract struct {
    ContractId          *int       `json:"contract_id"`
    CompanyId           *int       `json:"company_id"`
    DateEstablished     *time.Time `json:"date_established"`
    ExpiryDate          *time.Time `json:"expiry_date"`
    ExtensionExpiryDate *time.Time `json:"extension_expiry_date"`
    Description         *string    `json:"description"`
}

func main() {
    body := `{"contract_id":0,"date_established":"2022-04-03T00:00:00.000Z","expiry_date":null,"extension_expiry_date":null,"description":"fffff"}`

    var contract Contract
    reader := strings.NewReader(body)
    decoder := json.NewDecoder(reader)
    err := decoder.Decode(&contract)
    if err != nil {
        fmt.Println("Error: ", err)
    } else {
        fmt.Printf("Contract: %+v\n", contract)
    }
}

如果你不控制json,你需要写一个自定义的unmarshal method

这是我最终在 Flutter 中使用 Go 中的 pgtype.Datepgtype.DateTimestamptz api 以及 Postgresql 中的列类型 DATEDATETIME 实现的解决方案.我无法使用具有此数据类型的指针。

首先我在 Flutter 中创建了一个这样的助手:

import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';

extension DateTimeExtension on DateTime {
  String format([String pattern = 'dd/MM/yyyy', String? locale]) {
    if (locale != null && locale.isNotEmpty) {
      initializeDateFormatting(locale);
    }
    return DateFormat(pattern, locale).format(this);
  }

  String formatDbDateTime(
      [String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", String? locale]) {
    if (locale != null && locale.isNotEmpty) {
      initializeDateFormatting(locale);
    }
    return DateFormat(pattern, locale).format(this);
  }

  String formatDbDate([String pattern = 'yyyy-MM-dd', String? locale]) {
    if (locale != null && locale.isNotEmpty) {
      initializeDateFormatting(locale);
    }
    return DateFormat(pattern, locale).format(this);
  }

  String formatLocalDate([String pattern = 'dd MMMM yyyy', String? locale]) {
    if (locale != null && locale.isNotEmpty) {
      initializeDateFormatting(locale);
    }
    return DateFormat(pattern, locale).format(this);
  }

  String formatLocalDateTime(
      [String pattern = 'dd MMMM yyyy h:mm a', String? locale]) {
    if (locale != null && locale.isNotEmpty) {
      initializeDateFormatting(locale);
    }
    return DateFormat(pattern, locale).format(this);
  }
}

我在我的 Flutter 模型中使用它来格式化我的 Go 的日期 Api:

if (planAcceptedDate != null) {
  data['plan_accepted_date'] = planAcceptedDate!.formatDbDateTime();
} else {
  data['plan_accepted_date'] = null;
}

if (invoiceDate != null) {
  data['invoice_date'] = invoiceDate!.formatDbDate();
} else {
  data['invoice_date'] = null;
}

在我的 Flutter 视图表单中,我是这样使用它的:

        Container(
          padding: EdgeInsets.all(8.0),
          child: Text(
            _matter.planAcceptedDate == null
                ? ''
                : _matter.planAcceptedDate!.formatLocalDateTime(),
            style: TextStyle(
              color: appTextColor,
              fontWeight: FontWeight.normal,
              fontSize: _user.fontsize,
            ),
          ),
        ),
        Container(
          padding: EdgeInsets.all(8.0),
          child: Text(
            _matter.invoiceDate == null
                ? ''
                : _matter.invoiceDate!.formatLocalDate(),
            style: TextStyle(
              color: appTextColor,
              fontWeight: FontWeight.normal,
              fontSize: _user.fontsize,
            ),
          ),
        ),

我的 Go 结构如下所示:

PlanAcceptedDate pgtype.Timestamptz `json:"plan_accepted_date"`
InvoiceDate      pgtype.Date        `json:"invoice_date"`