Repository: prisma/prisma
File: packages/adapter-pg/src/conversion.ts (TypeScript)

Code before:
/****************************/
/* Time-related data-types  */
/****************************/

function normalize_numeric(numeric: string): string {
  return numeric
}

/****************************/
/* Time-related data-types  */
/****************************/

/*
 * DATE, DATE_ARRAY - converts value (or value elements) to a string in the format YYYY-MM-DD
 */

function normalize_date(date: string): string {
  return date
}

/*
 * TIMESTAMP, TIMESTAMP_ARRAY - converts value (or value elements) to a string in the rfc3339 format
 * ex: 1996-12-19T16:39:57-08:00
 */

function normalize_timestamp(time: string): string {
  // Parse timestamp manually to avoid JavaScript's 2-digit year interpretation issues
  // PostgreSQL format: "YYYY-MM-DD HH:MM:SS[.ffffff]"
  const match = time.match(/^(\d{1,4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?$/)
  if (!match) {
    // Fallback to original behavior for unexpected formats
    return new Date(`${time}Z`).toISOString().replace(/(\.000)?Z$/, '+00:00')
  }

  const [, year, month, day, hour, minute, second, fraction = '0'] = match
  const ms = fraction.padEnd(3, '0').slice(0, 3)

  // Use a safe year (2000) to avoid 2-digit year interpretation, then set the actual year
  const date = new Date(
    Date.UTC(
      2000,
      parseInt(month, 10) - 1,
      parseInt(day, 10),
      parseInt(hour, 10),
      parseInt(minute, 10),
      parseInt(second, 10),
      parseInt(ms, 10),
    ),
  )
  date.setUTCFullYear(parseInt(year, 10))


Review comment (suggestion):
I think there's a problem with putting the parsing logic in here, since this function is not invoked when `relationJoins = true`,
The only date parsing function we can rely on is `normalizeDateTime` in `packages/client-engine-runtime/src/interpreter/data-mapper.ts` when relationJoins are enabled

Code after:
/****************************/
/* Time-related data-types  */
/****************************/

function normalize_numeric(numeric: string): string {
  return numeric
}

/****************************/
/* Time-related data-types  */
/****************************/

/*
 * DATE, DATE_ARRAY - converts value (or value elements) to a string in the format YYYY-MM-DD
 */

function normalize_date(date: string): string {
  return date
}

/*
 * TIMESTAMP, TIMESTAMP_ARRAY - converts value (or value elements) to a string in the rfc3339 format
 * ex: 1996-12-19T16:39:57-08:00
 */

function normalize_timestamp(time: string): string {
  return `${time.replace(' ', 'T')}+00:00`
}

function normalize_timestamptz(time: string): string {
  return time.replace(' ', 'T').replace(/[+-]\d{2}(:\d{2})?$/, '+00:00')
}

/*
 * TIME, TIMETZ, TIME_ARRAY - converts value (or value elements) to a string in the format HH:mm:ss.f
 */

function normalize_time(time: string): string {
  return time
}

function normalize_timez(time: string): string {
  // Although it might be controversial, UTC is assumed in consistency with the behavior of rust postgres driver
  // in quaint. See quaint/src/connector/postgres/conversion.rs
  return time.replace(/[+-]\d{2}(:\d{2})?$/, '')
}

/******************/
/* Money handling */
/******************/