{"action":"created","issue":{"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/6","repository_url":"https://api.github.com/repos/googleapis/nodejs-bigquery","labels_url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/6/labels{/name}","comments_url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/6/comments","events_url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/6/events","html_url":"https://github.com/googleapis/nodejs-bigquery/issues/6","id":274952455,"number":6,"title":"losing precision in converting TIMESTAMP and INT64 to Javascript Number","user":{"login":"stephenplusplus","id":723048,"avatar_url":"https://avatars0.githubusercontent.com/u/723048?v=4","gravatar_id":"","url":"https://api.github.com/users/stephenplusplus","html_url":"https://github.com/stephenplusplus","followers_url":"https://api.github.com/users/stephenplusplus/followers","following_url":"https://api.github.com/users/stephenplusplus/following{/other_user}","gists_url":"https://api.github.com/users/stephenplusplus/gists{/gist_id}","starred_url":"https://api.github.com/users/stephenplusplus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephenplusplus/subscriptions","organizations_url":"https://api.github.com/users/stephenplusplus/orgs","repos_url":"https://api.github.com/users/stephenplusplus/repos","events_url":"https://api.github.com/users/stephenplusplus/events{/privacy}","received_events_url":"https://api.github.com/users/stephenplusplus/received_events","type":"User","site_admin":false},"labels":[{"id":753669709,"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/labels/api:%20bigquery","name":"api: bigquery","color":"ededed","default":false},{"id":753669710,"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/labels/priority:%20p2","name":"priority: p2","color":"ededed","default":false},{"id":753669711,"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/labels/status:%20acknowledged","name":"status: acknowledged","color":"ededed","default":false},{"id":753669712,"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/labels/type:%20bug","name":"type: bug","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2017-11-17T18:19:17Z","updated_at":"2017-11-17T18:19:19Z","closed_at":null,"author_association":"MEMBER","body":"_From @c0b on October 9, 2016 5:5_\n\nhttps://github.com/GoogleCloudPlatform/google-cloud-node/pull/1648#issuecomment-251383826\n\nThe BigQuery TIMESTAMP has up to microseconds precision, but when converting to a JavaScript Date, it becomes up to milliseconds\n\nhttps://github.com/GoogleCloudPlatform/google-cloud-node/pull/1648#issuecomment-251249300\n\nA JavaScript Number is really only a FLOAT64, there is no real INT64, so during conversion some precision is lost:\n\n``` js\n$ node ./bigquery/queries.js sync 'SELECT ARRAY<INT64>[0x7fff1234deadbeef, -0x8000000000000000] AS example_array'\n{ err: null,\n  rows: [ { example_array: [ 9223110580161593000, -9223372036854776000 ] } ],\n  nextQuery: null,\n  apiResponse: \n   { kind: 'bigquery#queryResponse',\n     schema: { fields: [ { name: 'example_array', type: 'INTEGER', mode: 'REPEATED' } ] },\n     jobReference: { ... },\n     totalRows: '1',\n     rows: [ { f: [ { v: [ { v: '9223110580161593071' }, { v: '-9223372036854775808' } ] } ] } ],\n     totalBytesProcessed: '0',\n     jobComplete: true,\n     cacheHit: false } }\nReceived 1 row(s)!\n[ { example_array: [ 9223110580161593000, -9223372036854776000 ] } ]\n```\n\nI don't really have a solution, please suggest when application need this much precision\n\n\n_Copied from original issue: GoogleCloudPlatform/google-cloud-node#1681_"},"comment":{"url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/comments/345322028","html_url":"https://github.com/googleapis/nodejs-bigquery/issues/6#issuecomment-345322028","issue_url":"https://api.github.com/repos/googleapis/nodejs-bigquery/issues/6","id":345322028,"user":{"login":"stephenplusplus","id":723048,"avatar_url":"https://avatars0.githubusercontent.com/u/723048?v=4","gravatar_id":"","url":"https://api.github.com/users/stephenplusplus","html_url":"https://github.com/stephenplusplus","followers_url":"https://api.github.com/users/stephenplusplus/followers","following_url":"https://api.github.com/users/stephenplusplus/following{/other_user}","gists_url":"https://api.github.com/users/stephenplusplus/gists{/gist_id}","starred_url":"https://api.github.com/users/stephenplusplus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stephenplusplus/subscriptions","organizations_url":"https://api.github.com/users/stephenplusplus/orgs","repos_url":"https://api.github.com/users/stephenplusplus/repos","events_url":"https://api.github.com/users/stephenplusplus/events{/privacy}","received_events_url":"https://api.github.com/users/stephenplusplus/received_events","type":"User","site_admin":false},"created_at":"2017-11-17T18:19:19Z","updated_at":"2017-11-17T18:19:19Z","author_association":"MEMBER","body":"I don't believe there is a good solution for this without introducing complexity.\r\n\r\n#### **TIMESTAMP**\r\n\r\n[The docs](https://cloud.google.com/bigquery/data-types) say that TIMESTAMPs are stored internally with microsecond precision, however, the raw API response seems to be returning the value in seconds.\r\n\r\n#### **INT64** \r\n\r\nThe solution for this would be a bit more complex for the user. Currently, if you read one of these values, you get the native JS \"Number\" type. For our `@google-cloud/spanner` API, the Spanner team wanted to guarantee the same precision the API stores, so this is how the \"more complex\" solution looks for that API: https://github.com/googleapis/nodejs-spanner/blob/8a8b43f52afdbcd443cdc6d6c5d0f2fa68ee5566/src/codec.js#L54-L66:\r\n\r\n```js\r\nfunction Int(value) {\r\n  this.value = value.toString();\r\n}\r\n\r\nInt.prototype.valueOf = function() {\r\n  var number = Number(this.value);\r\n\r\n  if (number > Number.MAX_SAFE_INTEGER) {\r\n    throw new Error('Integer ' + this.value + ' is out of bounds.');\r\n  }\r\n\r\n  return number;\r\n};\r\n```\r\n```js\r\ntable.read(query, function(err, rows) {\r\n  var row = rows[0]\r\n\r\n  row = [\r\n    {\r\n      name: 'SafeInt',\r\n      value: {\r\n        value: '2' // string\r\n      }\r\n    },\r\n    {\r\n      name: 'OutOfBoundsInt',\r\n      value: {\r\n        value: '--out-of-bounds-integer--' // string\r\n      }\r\n    }\r\n  ]\r\n\r\n  var safeInt = row[0].value\r\n  typeof safeInt === Spanner.Int\r\n  console.log(safeInt.value)\r\n  // '2' (String)\r\n  console.log(safeInt)\r\n  // 2 (Number type)\r\n\r\n  var outOfBoundsInt = row[1].value\r\n  typeof outOfBoundsInt === Spanner.Int\r\n  console.log(outOfBoundsInt.value)\r\n  // '--out-of-bounds-integer--' (String)\r\n  console.log(outOfBoundsInt)\r\n  // throws 'Integer '--out-of-bounds-integer-as-string--' is out of bounds.'\r\n})\r\n```\r\n\r\n@lukesneeringer how should we determine if the precision is worth the complexity?"}}
{"actor":{"display_login":"stephenplusplus"}}