How to create a momentJS object with a specfic time and a specific timezone(other than the default local time zone)? - momentjs

I will receive an string(with time and date) from the frontend. The string format is this "2021-08-16T23:15:00.000Z". I intend to declare a moment object with the input string, along with a specific timezone(other than the local one).
import moment from "moment";
import "moment-timezone";
// The input string I receive from the frontend.
let strTime = "2021-08-16T23:15:00.000Z";
console.log(strTime); //2021-08-16T23:15:00.000Z
let time = moment.tz(strTime, "YYYY-MM-DDTHH:mm:ss.SSSZ","America/Boise");
console.log(time); // Moment<2021-08-16T17:15:00-06:00>, undesired value
let UTCtime = moment.utc(time);
console.log(UTCtime);
As far as what I understood from this question, console.log(time) should output a moment object of time 23:15:00, but with timezone "America/Boise".
What I intend is time to have the same time i.e "23:15:00.000", with "America/Boise" as timezone.
So that when I later convert that time to UTC, I need to get the right value w.r.t the timezone "America/Boise" and not my local timezone. How can I do this.

I figured out a solution.
const momenttz = require("moment-timezone");
const moment = require("moment");
// The input string I receive from the frontend.
let strTime = "2021-08-16T23:15:00.000Z";
console.log(strTime); //2021-08-16T23:15:00.000Z
let time = moment.utc(strTime);
time.tz("America/Boise", true);
console.log(time.tz());
console.log(time); // Moment<2021-08-16T23:15:00-06:00>, desired value
let UTCtime = moment.utc(time);
console.log(UTCtime); // Moment<2021-08-17T05:15:00Z>
In the above code, at console.log(time),time has the value "23:15:00.000" with required timezone "America/Boise". This makes it possible for you to get the right value , when you later convert it to UTC.
This is made possible by passing an optional second parameter to .tz mutator of moment-timezone as true which changes only the timezone (and its corresponding offset), and does not affect the time value.
time.tz(timezone, true);
A sample example of using this is given in the answer code above.
You can read more about it here in the Moment Timezone Documentation

Related

Get time format according to spreadsheet locale?

I want to store a Javascript Date() object in a spreadsheet with correct format according to spreadsheet's locale (SpreadsheetApp.getActive().getSpreadsheetLocale()).
Is there a way to get the country specific (date and) time format string from the spreadsheet locale?
E.g. when locale is de_DE, time format string as hh:mm
but when locale is da_DK, time format string as hh.mm
Interesting as well how to get the countries currency format.
BTW when I have date and time in de_DE and than change to da_DK, dates are reformatted (23.01.2020 -> 23/01/2020) but times are not (it stays as 22:59). Is that an error in Spreadsheet?
Dates in JavaScript have the method toLocaleDateString, which return a string formatted according to the specified locale. But this doesn't seem to work in Apps Script.
If you're open to using an Apps Script Web App for this, you could use this toLocaleDateString in your client-side script (that is, in a script tag in your HTML).
If that's not the case, I think your best option would be to create the relationship between formats and locales yourself, because Apps Script doesn't have a built-in method to achieve that. You could, for example, use a switch statement that would check the locale, and then format the date accordingly with Utilities.formatDate, the tool Apps Script uses to format dates. It could be something along the following lines:
var locale = SpreadsheetApp.getActive().getSpreadsheetLocale();
var formattedDate;
switch (locale) {
case 'de_DE':
formattedDate = Utilities.formatDate(yourDate, yourTimeZone, "hh:mm");
break;
case 'da_DK':
formattedDate = Utilities.formatDate(yourDate, yourTimeZone, "hh.mm");
break;
// ...
}
return formattedDate;
Reference:
toLocateDateString
Apps Script Web Apps
Utilities.formatDate
I hope this is of any help.
Sorry for that, however I found a function that would be worth checking out, it's toLocaleDateString() and toLocaleTimeString (), they deliver the local date and time format.
Please check
Formato fechas JavaScript.
I did the test from Google Apps Script and it throws me the following
function pruebafecha() {
var d = new Date();
var n = d.toLocaleDateString();
var h = d.toLocaleTimeString();
Logger.log(n);
Logger.log(h);
}
This is the answer(Colombia):
[20-01-24 16:47:50:286 EST] 24 de enero de 2020
[20-01-24 16:47:50:287 EST] 16:47:50 EST
A JavaScript Date object includes date, time and timezone. When Google Apps Script pass a Date object to the spreadsheet using setValue() / setValues() the value is displayed according to the cell number formatting using the spreadsheet timezone.
If the cell formatting is set to Automatic by default the date will be displayed accordingly to the spreadsheet locale.
If you want to force the cell to display a date in an specific format use Class Range setNumberFormat / setNumberFormats
If you don't want to use the above methods and don't want to rely on the spreadsheet locale and automatic cell format then instead of passing a Date object pass the value as an string prepending it with an ' (apostrophe, single quote character) to prevent that that automatic data type parsing changes the value and it's format.
Related
Javascript in Google Sheets script: help using setNumberFormat
I don't know very well the configuration of the sheet you mention. However, I share a code that I use to print the date and time of data submission of a form.
var d = new Date();
var hour = d.getHours()-1;
var min = d.getMinutes();
var day = d.getDate();
var month = d.getMonth()+1;
var year = d.getFullYear();
if (month<10) {dia = day+"/"+"0"+month+"/"+year;}
else {dia = day+"/"+month+"/"+year;}
if (min<10){time = hour+":"+"0"+min;}
else {time = hour+":"+min;}
What I do in the code is to take the values โ€‹โ€‹of day, month and year, I add 1 to the value of month because it takes values โ€‹โ€‹[0:11] => [Jan, Dec].
Then I build the format I want from date and time, you can notice that I have 1 left to the hours, because when I did the tests I noticed that the time of the script was one hour above.
I use google translate, I hope it is understood.

How do I go from a NaiveDate to a specific TimeZone with Chrono?

I am parsing dates and times in Rust using the chrono crate. The dates and times are from a website in which the date and time are from different sections of the page.
The date is shown in the format %d/%m/%Y (example: 27/08/2018). The time is shown with only the hour (example: 12, 10, 21, etc.)
I want to store these datetimes as UTC so that I can compute time remaining until a given datetime from now in a "timezone agnostic" way. I know which timezone these datetimes are from (Paris time).
I created a NaiveDate from the date input (this is a work in progress so there's no error handling yet):
let naive_date = NaiveDate::parse_from_str(date, "%d/%m/%Y").unwrap()
From that point on, what would be the best way to get the UTC DateTime, given that I have a string with the hour?
I am lost in the various TimeZone/Offset traits, and do not know if I should use a Local, or FixedOffset and then convert to Utc.
The Chrono documentation could probably be improved to make it easier to find how to do these things.
Assuming this is your starting point:
use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
// The date you parsed
let date = NaiveDate::from_ymd(2018, 5, 13);
// The known 1 hour time offset in seconds
let tz_offset = FixedOffset::east(1 * 3600);
// The known time
let time = NaiveTime::from_hms(17, 0, 0);
// Naive date time, with no time zone information
let datetime = NaiveDateTime::new(date, time);
You can then use the FixedOffset to construct a DateTime:
let dt_with_tz: DateTime<FixedOffset> = tz_offset.from_local_datetime(&datetime).unwrap();
If you need to convert it to a DateTime<Utc>, you can do this:
let dt_with_tz_utc: DateTime<Utc> = Utc.from_utc_datetime(&dt_with_tz.naive_utc());
I've discovered chrono-tz and found it much easier to use. For example:
pub fn create_date_time_from_paris(date: NaiveDate, time: NaiveTime) -> DateTime<Utc> {
let naive_datetime = NaiveDateTime::new(date, time);
let paris_time = Paris.from_local_datetime(&naive_datetime).unwrap();
paris_time.with_timezone(&Utc)
}
The dates and times are from a website in which the date and time are from different sections of the page.
Here's an example of how you can incrementally parse multiple values from distinct strings, provide default values for unparsed information, and use Chrono's built-in timezone conversion.
The key is to use the parse function to update a Parsed struct. You can use the StrftimeItems iterator to continue to use more readable format strings.
extern crate chrono;
use chrono::prelude::*;
fn example(date: &str, hour: &str) -> chrono::ParseResult<DateTime<Utc>> {
use chrono::format::{self, strftime::StrftimeItems, Parsed};
// Set up a struct to perform successive parsing into
let mut p = Parsed::default();
// Parse the date information
format::parse(&mut p, date.trim(), StrftimeItems::new("%d/%m/%Y"))?;
// Parse the time information and provide default values we don't parse
format::parse(&mut p, hour.trim(), StrftimeItems::new("%H"))?;
p.minute = Some(0);
p.second = Some(0);
// Convert parsed information into a DateTime in the Paris timezone
let paris_time_zone_offset = FixedOffset::east(1 * 3600);
let dt = p.to_datetime_with_timezone(&paris_time_zone_offset)?;
// You can also use chrono-tz instead of hardcoding it
// let dt = p.to_datetime_with_timezone(&chrono_tz::Europe::Paris)?;
// Convert to UTC
Ok(dt.with_timezone(&Utc))
}
fn main() {
let date = "27/08/2018";
let hour = "12";
println!("dt = {:?}", example(date, hour)); // Ok(2018-08-27T11:00:00Z)
}

Xpages Date Time

I'm going loopy....
I want a date, in date format, for example
21/06/2017 17:23:04 GDT
I stamp this on a document, but I then want to display it on my xpage as:
21/06/2017 17:23
But I keep getting different results no matter what I do. I get the date from the onClick of a button using
var dt = new Date();
I then pass this into a function:
function AddObjectivesHistoryItem(doc, dt, action, username){
var ArrDocHistory:array = doc.getItemValueArray("History");
if(ArrDocHistory.length < 1){
// This should always return an object as it is created when an objectives document is first
// created but do this check to be safe and create an array if for some reason it doesnt exist
ArrDocHistory = [dt+"|"+action+"|"+username];
}else{
// append new value to the array
ArrDocHistory.push(dt+"|"+action+"|"+username);
}
doc.replaceItemValue("History",ArrDocHistory);
doc.replaceItemValue("LastUpdatedByName",username);
doc.replaceItemValue("LastUpdatedDate",dt);
}
I've tried using toLocaleString() and all others it seems but it wont work.
For example, toLocaleString() displays as 13-Mar-2018 15:02:15 on my xpage. It's close to what I want except it uses hyphens instead of slashes, and also displays the seconds.
I've tried using custom date pattern on my date field properties with no luck and I'm certain I'm missing something super obvious!?
Any pointers on how to firstly get the date like 21/06/2017 17:23:04 GDT and store as a date and secondly to then display it as 21/06/2017 17:23, this can be a string if it needs to be.
Thanks
You can get your date value as String in SSJS with:
var dateTimeFormat = new java.text.SimpleDateFormat("dd/MM/yyyy kk:mm");
var dateTimeString = dateTimeFormat.format(dt)));
If you want to store as text, java.text.SimpleDateFormat is best for converting a date server-side to a specific text format. It can also be used in a converter to manipulate to/from as well.

Java 8 Parse ISO-8601 date ignoring presence (or absence) of timezone

My application should be able to parse date ignoring timezone (I always know for sure that it is UTC). The problem is that the date might come in both following forms -
2017-09-11T12:44:07.793Z
0001-01-01T00:00:00
I can parse the first one using LocalDateTime, and the second one using Instant class. Is there a way to do that using a single mechanism?
P.S. I'm trying to avoid hardcoding Z at the end of the input string
If the Z offset is optional, you can use a java.time.format.DateTimeFormatterBuilder with an optional section:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter
.toFormatter();
Then you can use the parseBest method, with a list of TemporalQuery's that tries to create the correspondent object. Then you check the return type and act accordingly:
Instant instant = null;
// tries to create Instant, and if it fails, try a LocalDateTime
TemporalAccessor parsed = fmt.parseBest("2017-09-11T12:44:07.793Z", Instant::from, LocalDateTime::from);
if (parsed instanceof Instant) {
instant = (Instant) parsed;
} else if (parsed instanceof LocalDateTime) {
// convert LocalDateTime to UTC instant
instant = ((LocalDateTime) parsed).atOffset(ZoneOffset.UTC).toInstant();
}
System.out.println(instant); // 2017-09-11T12:44:07.793Z
Running with the second input (0001-01-01T00:00:00) produces the Instant equivalent to 0001-01-01T00:00:00Z.
In the example above, I used just Instant::from and LocalDateTime::from, so the formatter tries to first create an Instant. If it's not possible, then it tries to create a LocalDateTime. You can add as many types you want to that list (for example, I could add ZonedDateTime::from, and if a ZonedDateTime is created, I could just convert to Instant using toInstant() method).
As you know for sure that the input is always in UTC, you can also set it directly in the formatter:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter with UTC
.toFormatter().withZone(ZoneOffset.UTC);
So you can parse it directly to Instant:
System.out.println(Instant.from(fmt.parse("2017-09-11T12:44:07.793Z"))); // 2017-09-11T12:44:07.793Z
System.out.println(Instant.from(fmt.parse("0001-01-01T00:00:00"))); // 0001-01-01T00:00:00Z
You can "parseBest", like this:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[Z]");
Temporal parsed = parser.parseBest(inputString, Instant::from, LocalDateTime::from);
Then you should check what did get parsed, and act accordingly.
The parseBest method will work with any type of TemporalQuery, including most of from methods available on java.time classes. So you can lengthen that list with LocalDate.from, for example.
You can also use that method and lambdas to coerse parse results to the type you want without having instanceof checks that are external for result resolution (although not without one cast):
Instant parsed = (Instant) parser.parseBest(inputString,
Instant::from,
interResult -> LocalDateTime.from(interResult).atZone(ZoneOffset.UTC).toInstant())
Notice that second option uses lambda that converts LocalDateTime to ZonedDateTime and then to Instant, so the parse results are always coersed to Instant.

Drop timezone before format

I want to add one second to random time in ISO format, e.g.
var t = "2015-01-13T00:00:00+11:00";
moment(t).add(1, "second").format(); // expected "2015-01-13T00:00:01+11:00", but get "2015-01-12T18:00:01+05:00"
So it converts t to current browser timezone (+05:00 in my case) and only then adds a second.
How can I drop timezone before adding and return it after?
I found:
moment.parseZone(t).add("1", "second").format(); // "2015-01-13T00:00:01+11:00"

Resources