Filename Extension: .6nf
1. Introduction
6NF File Format is a new bitemporal, sixth-normal-form (6NF)-inspired data exchange format designed for DWH and for reporting. It replaces complex hierarchical formats like XBRL, XML, JSON, and YAML.
2. Design Principles
Database Friendly Flat Structure : No nested objects or arrays. No need for parsing
6NF Compatibility : Direct mapping to 6NF database tables. No need for normalization
Bitemporal Database Compatibility : All data includes valid_from and recorded_at timestamps
UTC Time Standard : All timestamps must be in UTC format, denoted by the 'Z' suffix (e.g., 2023-01-01T12:00:00Z)
Struct Grouping : Multiple attributes with shared temporal context
Compactness : Uses Crockford’s Base32 - encoded UUIDv7 for identifiers
Readability : Clean syntax with minimal punctuation
PostgreSQL Style : Uses snake_case notation of identifiers (names)
Case Sensitivity : Keywords are UPPERCASE and case-sensitive. Identifiers (names) are lowercase and case-sensitive
UTF-8 Encoding: Files use UTF-8 encoding
3. Syntax (EBNF)
6nf = [version] { entity | reference | attribute | attribute_ref | struct | relationship } ; version = "VERSION" number "
" ; entity = "ENTITY" entity_name entity_id "
" ; reference = "REFERENCE" name reference_id value "
" ; attribute = "ATTRIBUTE_OF" entity_name entity_id name value valid_from recorded_at "
" ; attribute_ref = "ATTRIBUTE_REF_OF" entity_name entity_id name reference_id valid_from recorded_at "
" ; struct = "STRUCT_OF" entity_name entity_id name valid_from recorded_at "
" { name (value | reference_id) "
" } ; relationship = "RELATIONSHIP" name relationship_id valid_from recorded_at "
" { name ( entity_id | reference_id ) "
" } ; value = string | number | iso8601 | "true" | "false" ; string = "\"" { character } "\"" ; number = [ "-" ] digit { digit } [ "." digit { digit } ] ; valid_from = iso8601 ; recorded_at = iso8601 ; entity_name = ( letter | "_" ) { letter | digit | "_" } ; name = ( letter | "_" ) { letter | digit | "_" } ; entity_id = 26 * base32_char ; reference_id = 26 * base32_char ; relationship_id = 26 * base32_char ; base32_char = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "J" | "K" | "M" | "N" | "P" | "Q" | "R" | "S" | "T" | "V" | "W" | "X" | "Y" | "Z" ;
4. Example