Skip to content
Astera Technology

Why did quantity 1.234,5 import as 1.234?

Apply the declared decimal-comma grammar rather than a prefix-consuming parser.

Download complete case notes and answer keys ↓

Read the source and its declared rule

This original quantity format uses comma decimal and optional dot-separated groups of three digits. No sign or spaces are allowed; whole-part leading zeros are forbidden except zero itself. It permits nonnegative finite values up to 1,000,000 and retains source text. parseFloat stops at the comma; the corrected grammar validates the whole representation before converting to a JavaScript Number.

Filled synthetic input
RecordInput JSON
Base input{"raw":"1.234,5"}
Download editable CSV ↓

Compare the actual paths

Removing approved grouping dots and changing the declared decimal comma produces 1234.5. This is not a guess about an unknown locale or a currency conversion.

Misleading and corrected outputs
PathOutput JSON
Misleading path{"accepted":true,"value":1.234,"source":"1.234,5"}
Corrected path{"accepted":true,"value":1234.5,"source":"1.234,5"}
Download editable CSV ↓
Local Node.js program: 22.23.3 or 24.14.1
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};

import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
    if(!corrected)return {accepted:true,value:parseFloat(i.raw),source:i.raw};
    if(!/^(?:0|[1-9]\d*|[1-9]\d{0,2}(?:\.\d{3})+)(?:,\d+)?$/.test(i.raw))return {accepted:false,error:'decimal-comma-grammar',source:i.raw};
    const value=Number(i.raw.replace(/\./g,'').replace(',','.'));
    if(!Number.isFinite(value)||value>1000000)return {accepted:false,error:'outside-supplied-range',source:i.raw};
    return {accepted:true,value,source:i.raw};
  };
const cases=[{"label":"misleading base","input":{"raw":"1.234,5"},"expected":{"accepted":true,"value":1.234,"source":"1.234,5"},"corrected":false},{"label":"corrected base","input":{"raw":"1.234,5"},"expected":{"accepted":true,"value":1234.5,"source":"1.234,5"},"corrected":true},{"label":"mixed separator conventions","input":{"raw":"1,234.5"},"expected":{"accepted":false,"error":"decimal-comma-grammar","source":"1,234.5"},"corrected":true},{"label":"canonical zero","input":{"raw":"0"},"expected":{"accepted":true,"value":0,"source":"0"},"corrected":true}];
for(const test of cases){
  const actual=run(test.input,test.corrected);
  assert.deepEqual(actual,test.expected,test.label);
  console.log(test.label,actual);
}
Download runnable example ↓

Check boundaries before the next load

Mixed 1,234.5 is rejected. Canonical zero remains a real zero quantity.

Editable boundary records and expected outputs
CaseInput JSONExpected output JSON
Mixed separator conventions{"raw":"1,234.5"}{"accepted":false,"error":"decimal-comma-grammar","source":"1,234.5"}
Canonical zero quantity{"raw":"0"}{"accepted":true,"value":0,"source":"0"}
Download editable CSV ↓

What value does 1.234,5 mean under this supplied contract?

Show the worked answer

1234.5. The bad 1.234 is only a consumed prefix; mixed separator conventions must not be guessed.

Related resources