Nick Petrie
Nick Petrie

Reputation: 5598

Convert time from specific timezone to UTC (ColdFusion/Java)

We need to take a datetime string (which we've already received and validated from user form inputs), treat it as being specific to the America/New_York timezone, and convert it to UTC.

We're currently running ColdFusion 2018, which is limited in its native datetime functionality. So I wanted to tap into the underlying Java. Most CF-related solutions are pre-java.time, so I attempted my own based on other Stack Overflow answers. Hoping someone with more Java knowledge can review this solution. (This is in CF Script, but it should be pretty self-documenting.) Is this correct and is there a better/more efficient solution?

var validatedDateTime = '2022-06-29T14:30:00';

LocalDateTime = createObject('java', 'java.time.LocalDateTime');
ZoneID = createObject('java', 'java.time.ZoneId');
ZoneOffset = createObject('java', 'java.time.ZoneOffset');

ldt = LocalDateTime.parse(validatedDateTime);
nyZone = ZoneID.of('America/New_York');
odt = ldt.atOffset(nyZone.getRules().getOffset(ldt));
utcDateTime = odt.withOffsetSameInstant(ZoneOffset.UTC).toLocalDateTime();```

Upvotes: 1

Views: 770

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338614

tl;dr

You said:

The question is more about taking a datetime string (e.g. '2022-06-29T14:30:00'), adding the America/New_York timezone to it, and converting it to UTC.

LocalDateTime
.parse( "2022-06-29T14:30:00" )      // “taking a datetime string (e.g. '2022-06-29T14:30:00')”
.atZone( 
    ZoneId.of( "America/New_York" )  // “adding the America/New_York timezone to it”
)                                    // Returns a `ZonedDateTime` object. 
.toInstant()                         // “converting it to UTC”

See this code run live at Ideone.com.

2022-06-29T18:30:00Z

Details

You neglected to mention your database engine and the precise type of your column. So we cannot give a full answer. I can address part of it.

So the goal is to take the user's date & time, treat it like America/New_York, and convert it to UTC.

DateTimeFormatter fDate = DateTimeFormatter. … ;  // Define a formatter to match the format used by your user. 
LocalDate ld = LocalDate.parse( inputDate , fDate ) ;

Trap for DateTimeParseException to detect faulty inputs.

Do similarly for LocalTime.

DateTimeFormatter fTime = DateTimeFormatter. … ;  // Define a formatter to match the format used by your user. 
LocalTime lt = LocalDate.parse( inputTime , fTime ) ;

Combine with time zone to determine a moment.

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt =
ZonedDateTime.of( ld , lt , z ) ;

Adjust to UTC.

Instant instant = zdt.toInstant() ;

All of this has been covered many many times on Stack Overflow. Search to learn more.

Upvotes: 1

Redtopia
Redtopia

Reputation: 5237

Here’s what I do:

Like you, I store timestamps in UTC. Then I output them into the DOM in ISO-8601 format wrapped in a element so I can then find them and and convert them in the browser using any number of JavaScript libraries. I use sugar.js, which I love.

The advantage to doing it this way is that because the timestamp is rendered in the browser, it will use the current time and time zone that is set on that computer. The result is that the timestamp will be rendered locally no matter what timezone they are in.

For example, on the server in ColdFusion, the following code converts your local server time to UTC. Even if your server is in UTC, I think you should do this just to always be sure.

utc = DateConvert(“Local2UTC”, now());

Then, output the date in ISO where it goes in the DOM:

writeOutput('<span class="isodate">#DateFormat(utc, "YYYY-MM-DD")#T#TimeFormat(utc, "HH:mm:ss.l")#Z</span>');

The browser will get:

<span class="isodate">2022-06-29 15:00:00.000Z</span>

Then write some JavaScript code to find those isodate elements and convert them. In sugar.js it looks something like (I'm using jquery just to make it easy to understand):

$('span.isodate').each(function(ix,elem) {
    var iso = $(elem).text(),
        d = Date.create(iso),
        localDate = d.format('{Weekday}, {Month} {d}, {yyyy} at {h}:{mm} {tt} (' + d.relative() + ')');
    $(elem).text(localDate);
});

Of course you can use whatever format you want, or whatever Javascript library you want to convert the date. momentjs.com is another one, but a little more complex. Sugar.js is super lightweight and easy to use and has great date support.

These code snippets above demonstrate the pieces of the puzzle and have not been tested. You could make it all work however you want... for example, I have a ColdFusion function that generates an ISO-8601 string for given a date. I've also got javascript functions that make it easy to find and convert these elements to local time. Good luck!

Upvotes: 0

Related Questions