Проблема
ОП вводит 14022019 в неформатированную ячейку.Когда ячейка отформатирована как дата, возвращается значение 24 декабря 40290;ФП ожидала, что дата будет 14 февраля 2019 года.
Решение
- 1: отформатируйте ячейку как дату до ввода данных.
-2: введите число с разделителями , например 14/02/2019 или 14-02-2019
Пояснение
Когда OP вводит "14022019" вв неформатированной ячейке они предполагают, что ввод должен рассматриваться как дата (14 февраля 2019 г.).Однако Google рассматривает содержимое по номинальной стоимости;нет никаких выводов о дате / времени.Так, когда ячейка впоследствии форматируется как дата, необработанное значение преобразуется в дату, и ячейка отображает 24 декабря 40290.
Причина в том, что эпоха времени Google началась 31 декабря 1899 г. 00:00:00 (в отличие от Unix Time Epoch, , который используется Javascript , который начался 1 января 1970 года 00:00:00).Во-вторых, Google измеряет дату и время в днях (в отличие от эпохи Unix, которая измеряет прошедшие секунды).
Это ( примерно ), как Google конвертирует 14 022 019 в 24 декабря 40290.
- 14 022 019 "дней", в среднем примерно 365 245 дней в году = примерно 38 390,7 года.
- Добавьте 1899 для эпохи Google.Промежуточный итог = 40289,7 года.(примерно середина сентября 40290)
- с учетом корректировок для високосных годов 101,795 дней = 0,3 (101,795 / 365,245);Промежуточный итог = 40290 лет.(примерно 24 декабря 40290)
Примечание # 1: есть еще одно осложнение.
Способ, которым Sheets и Apps Script обрабатывают "даты", очень различаются.
- Листы: единица «дата» составляет 1 день;Базовая дата - 1899-12-30 0:00:00, получая часовой пояс из настроек электронной таблицы.
- Сценарий приложений (основанный на JavaScript): единица «дата» равна 1 миллисекунде.Базовая дата 1970-1-1 00:00:00 UTC.
Ссылка / Кредит: Рубен
Примечание № 2: Моя ссылка для эпохи Google: (https://webapps.stackexchange.com/a/108119/196152)
Примечание № 3: В целом преобразования даты / времени основаны на 3600 секунд в час, 86 400 секунд в день, 31 556 926 секунд в год и 365,24 дней в году.
ОБНОВЛЕНИЕ - 20Фев 2019
ОП совершенно справедливо спрашивает: «Как мне преобразовать существующие ячейки?»
Код для преобразования прост: - преобразовать число в строку - срезстрока в компоненты для дня, месяца и года - используйте компоненты для создания новой даты - обновите ячейку с датой
Потенциальный вопрос для диапазона, который необходимо преобразовать. Что такое диапазон, это диапазонвсегда один и тот же размер и т. д. Следующий код позволяет пользователю выбрать диапазон для интерфейса. Затем этот диапазон можно преобразовать. Возможно, этот элемент не был необходим, но он обеспечивает более гибкое, если не элегантное, решение.
Code.gs
function onOpen(){
SpreadsheetApp.getUi()
.createMenu("Date Convert")
.addItem("Convert", "selRange")
.addToUi();
}
function selRange()//run this to get everything started. A dialog will be displayed that instructs you to select a range.
{
var output=HtmlService.createHtmlOutputFromFile('pickRange').setWidth(300).setHeight(200).setTitle('Convert to dates');
SpreadsheetApp.getUi().showModelessDialog(output, 'Convert Numbers to Dates');
}
function selCurRng()
{
var sso=SpreadsheetApp.getActive();
var sh0=sso.getActiveSheet();
var rg0=sh0.getActiveRange();
var rng0A1=rg0.getA1Notation();
rg0.setBackground('#FFC300');
return rng0A1;
}
function clrRange(range)
{
var sso=SpreadsheetApp.getActive();
var sh0=sso.getActiveSheet();
var rg0=sh0.getRange(range);
rg0.setBackground('#ffffff');
}
function convertnumbertodate(crange){
// establish spreadsheet credentials
var ss1=SpreadsheetApp.getActive();
var sh1=ss1.getActiveSheet();
// get the range so that rows and columns can be calculated
var rg1=sh1.getRange(crange);
// get number of columns
var numColumns = rg1.getNumColumns();
// if more than one column chosen, stop the process.
if (numColumns !=1){
//Logger.log("DEBUG: Number of columns in range = "+numColumns); // DEBUG
var message = "Too Many Columns; one column only";
return message;
}
// get the first row and the number of rows
var rowqty = 1;
var rownum = rg1.getRow();
// Logger.log("DEBUG: first row = "+rownum);//DEBUG
var rowqty = rg1.getNumRows();
// Logger.log("DEBUG: Number of rows = "+rowqty); //DEBUG
// get the values - different syntax for a single cell vs range
if (rowqty !=1){
// Multiple cells - uset GetValues
var rangevalues = rg1.getValues();
}
else {
// single cell, use getValue
var rangevalues = rg1.getValue();
}
//Logger.log("DEBUG: Values = "+rangevalues); //DEBUG
// create array for temporary storage
var newvalues = [];
// loop through the values
for (var i=0; i< rowqty; i++){
// different treatment for single cell value
if (i!=0 && rowqty !=1){
// multiple cells
var nstring = rangevalues[i].toString();
}
else {
// single value cell
var nstring = rangevalues.toString();
}
Logger.log("DEBUG: Value of the string is = "+nstring); //DEBUG
// slice the string in day, month and year
var daystring = nstring.slice(0, 2);
var monthstring = nstring.slice(2, 4);
var yearstring = nstring.slice(4, 8);
//calculate the date
var pubdate = new Date(yearstring, monthstring - 1, daystring);
//Logger.log("DEBUG: the date is "+pubdate); //DEBUG
// push the value onto the aray
newvalues.push([pubdate]);
}
// set the value(s)
if (rowqty !=1){
// Multiple cells - uset GetValues
rg1.setValues(newvalues)
}
else {
// single cell, use getValue
rg1.setValue(newvalues);
}
//rg1.setValues(newvalues);
var message = "Update complete";
rg1.setBackground('#ffffff');
return message;
}
pickRange.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var grange='';
function selectRange()
{
$('#btn1').prop('disabled',true);
$('#btn2').prop('disabled',false);
google.script.run
.withSuccessHandler(setResponse)
.selCurRng();
}
function setResponse(r)
{
grange=r;
var msg='Selected range: ' + r+". Ready to convert";
$('#instr').css('display','none');
$('#rsp').text(msg);
}
function convert2date()
{
$('#btn1').prop('disabled',false);
$('#btn2').prop('disabled',false);
google.script.run
.withSuccessHandler(setResponse02)
.convertnumbertodate(grange);
}
function setResponse02(q)
{
qnumber=q;
var msg= q;
$('#instr').css('display','none');
$('#rsp').text(msg);
}
function clearAndClose()
{
google.script.run.clrRange(grange);
google.script.host.close();
}
console.log('My Code');
</script>
</head>
<body>
<div id="rsp"></div>
<div id="instr">Select range - <b>One column limit</b></div>
<br/>
<input type="button" id="btn1" value="1 - Select a range" onClick="selectRange();" />
<br />
<input type="button" id="btn3" value="2 - Convert numbers to dates" onClick="convert2date();" />
<br />
<input type="button" id="btn2" value="close" onClick="clearAndClose();"; disabled="true" />
</body>
</html>
Credit
// Запрашивать у пользователя диапазон.Функция gs, передача массива в html-скрипт и переориентация на HTML-диалог // кредитный ответ Купера - https://stackoverflow.com/a/45427670/1330560
ADDENDUM
Если диапазон, в котором вводятся псевдо-даты, известен и не изменяется, то код для его управления упрощается
function onEdit(e) {
// establish spreadsheet credentials
var ss1 = SpreadsheetApp.getActive();
var sh1 = ss1.getActiveSheet();
// get the onEdit parameters
var debug_e = {
authMode: e.authMode,
range: e.range.getA1Notation(),
source: e.source.getId(),
user: e.user,
value: e.value,
oldValue: e.oldValue
};
//Logger.log("AuthMode: "+debug_e.authMode+"\n, Range: "+debug_e.range+"\n, source: "+debug_e.source+"\n, user: "+debug_e.user+"\n, value: "+debug_e.value+"\n, old value: "+debug_e.oldValue);
// Note the range for data entry is known and fixed.
// it is "D3:D31"
// Target range for converting numbers to dates
// set the column
var column = 4; // column D
// get the first row and the number of rows
var rowqty = 29;
var rowfirst = 3;
var rowlast = 31;
//Logger.log("DEBUG: first row = "+rowfirst+", last row = "+rowlast+", number of rows = "+rowqty);//DEBUG
// get detail of the edited cell
var editColumn = e.range.getColumn();
var editRow = e.range.getRow();
//Logger.log("DEBUG: edited column = "+editColumn+", edited row "+editRow);//DEBUG
//test if the edited cell falls into the target range
if (editColumn == 4 && editRow >= rowfirst && editRow <= rowlast) {
// the edit was in the target range
var nstring = e.value.toString();
//Logger.log("DEBUG: Value of the string is = "+nstring); //DEBUG
// slice the string in day, month and year
var daystring = nstring.slice(0, 2);
var monthstring = nstring.slice(2, 4);
var yearstring = nstring.slice(4, 8);
//calculate the date
var pubdate = new Date(yearstring, monthstring - 1, daystring);
//Logger.log("DEBUG: the date is "+pubdate); //DEBUG
e.range.setValue(pubdate)
} else {
//Logger.log("DEBUG: Nothing to see here; this cell not in the target range");//DEBUG
}
}