+2 votes
by (380 points)
Hello all, i'm completely new here, and twine in general.

The last two weeks i've been watching lots of tutorials on YT, and a whole bunch of threads explaining how to do certain things.

I have an idea to create a relatively big, open world management game, i already know how to use some macros, but right now i can't continue without having a decent, simple, easy to use date and calendar system that counts time (only hours and minutes).

The story format i'm using is Sugarcube 2.21.0, on Twine 2.2.1.

I never dabbled in JS before, or any kind of coding in general, hence my ignorance.

My other problem is that most of the threads i find about how to make a clock system, are either for twine 1 or earlier versions of sugarcube, and not applicable to my case.

What i'm looking for essentially is a timer that counts time as a normal clock would, but only counts time through entering passages, for example, a sleep passage makes time go by 8hours, another makes time pass by 1minute, and so forth. And if it could count days and months as well, that'd be perfect.

I know this question gets asked a lot, and i don't want to add to the pile, but i'm tired of banging my head against the wall.

Can someone help me, please?

3 Answers

+1 vote
by (8.5k points)
selected by
Best answer

In the simplest case, for Earth dates in the Gregorian calendar, just use the standard JavaScript Date object. Set some value to it at the beginning of your game (in StoryInit or your starting passage) and you can always refer to it later to add or change the "current" time.

<<set $now = new Date("2238-07-05T10:30:00Z")>>

The Date object, for all its faults, has the neat ability that its numbers "overflow". For example, if you'd add 20 hours to this particular date and print it, it would be the morning of the 6th July, not the 30th hour of the 5th July.

<<run $now.setHours($now.getHours() + 20)>>
<<= $now.toGMTString()>>
/* prints "Fri, 06 Jul 2238 06:30:00 GMT" */

You can add some macros around this, in particular for the display, and you can also look at the moment.js module if you want even better control over dates and times. But to know what exactly to suggest here we'd need way more specifics about your requirements for manipulating and displaying the date and time.

For an example of a bit of possible "chrome" to polish your game with, take a look at the dyClockJS module.

by (380 points)
Thanks a lot for the detailed explanation.

You cleared things a bit more for me, but now i see my greatest obstacle will be JavaScript, as everytime i see javascripts i get a small seizure, how big and complex they are, specially for me, one who never programed anything in my life.

This is all very new, and very different from anything i've done, but i'll get there in time.

Thanks a lot again.

Any kind of help is appreciated and welcome! =)
+1 vote
by (36.8k points)
by (380 points)
Thank you for your reply, but seeing as i'm still watching tutorials and learning to control Sugarcube, all of these leave me with more answers than questions. I'll learn eventually though, at least i have three links to some examples i can apply in the future.


Thank you again. =)
+2 votes
by (8.7k points)
  • Create a new passage called "Game Clock".
  • Add a widget tag to this passage.
  • Paste Mad Exile's Gregorian Date & Time Widgets into this passage:
	Date & Time Widget Setup
	window.GameDays to [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
	window.GameMonths to [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"

		Below we have to use the multi-parameter version of the Date
		constructor, rather than the date string version, because the
		date string version treats a missing timezone offset as UTC.
		While there are ways to determine players' timezone offsets,
		so they could be added to a date string, it's more convenient
		simply to use the multi-parameter constructor.

		The point of this is so that you can simply initialize the game
		world clock to whatever date and time you wish without having to
		worry about the players' timezone offsets, while still ensuring
		that they all see the same game world dates and times.
	/* params: year , month(0-based) , day , hour(24H) , minute [, second ] */
	$gameDate to new Date(2015, 2, 17, 3, 24); /* e.g. Mar 17, 2015 03:24 */

	Date & Time Advancement Widget Definitions
/* Adds the specified number of minutes. */
<<widget "addmins">>\
<<run $gameDate.setMinutes($gameDate.getMinutes() + $args[0])>>\

/* Adds the specified number of hours. */
<<widget "addhours">>\
<<run $gameDate.setHours($gameDate.getHours() + $args[0])>>\

/* Adds the specified number of days. */
<<widget "adddays">>\
<<run $gameDate.setHours($gameDate.getHours() + $args[0] * 24)>>\

	Date & Time Printing Widget Definitions
/* Prints the current date ("{weekday} {month} {day}, {year}"). */
<<widget "date">>\
<<print String.format("{0} {1} {2}, {3}",

/* Prints the current time (12H). */
<<widget "time12hr">>\
<<if $gameDate.getHours() eq 0>>\
<<elseif $gameDate.getHours() gt 12>>\
<<print $gameDate.getHours() - 12>>\
<<print $gameDate.getHours()>>\
<<if $gameDate.getMinutes() lt 10>>0<</if>><<print $gameDate.getMinutes()>> \
<<if $gameDate.getHours() gte 12>>PM<<else>>AM<</if>>\

/* Prints the current time (24H). */
<<widget "time24hr">>\
<<if $gameDate.getHours() lt 10>>0<</if>><<print $gameDate.getHours()>>:\
<<if $gameDate.getMinutes() lt 10>>0<</if>><<print $gameDate.getMinutes()>>\

/* Prints the current date and time (12H). */
<<widget "datetime">><<date>> <<time12hr>> (<<time24hr>>)<</widget>>
  • To advance the time 5 minutes in a passage, type <<addmins 5>> somewhere into the passage.
  • To advance 7 hours, <<addhours 7>>
  • To advance 30 days, <<adddays 30>>
ago by (8.7k points)

To set the date to midnight Jan 1, 1885

<<set $gameDate to new Date(1885, 0, 1, 0, 0)>>


To set the date to 9.28AM Nov 12, 1955

<<set $gameDate to new Date(1955, 10, 12, 9, 28)>>


To set the date to 2.42AM Oct 27, 1985

<<set $gameDate to new Date(1985, 9, 27, 2, 42)>>
ago by (110 points)
edited ago by

I believe the issue was about how to set the hour for example, without changing the day. Seeing as in some game systems it's impossible to tell on which day the player is going to sleep in their bed on. If there are other ways for days to pass, for example.

<<set $gameDate.setHours(8)>> 

 sets the time to 8 AM

<<set $gameDate.setHours(16)>>

sets the time to 4 PM

So, for instance, writing this in your 'bed time passage'...

<<adddays 1>>
<<set $gameDate.setHours(8)>>

Will take you to 8AM tomorrow morning. I've not studied making widgets, so not sure how to make a neat 'sethour' widget, but I guess I could look into that.

ago by (100 points)

I tried this but it sets it to the wrong hour- say if I do the 

<<set $gameDate.setHours(16)>>

it sets the time to 9 pm, not 4. I'm not sure why. 

ago by (110 points)

There's something wrong with your code somewhere. By default, it should work.

var event = new Date('August 19, 1975 23:15:30');

// expected output: Tue Aug 19 1975 20:15:30 GMT+0200 (CEST)
// (note: your timezone may vary)


// expected output: Tue Aug 19 1975 20:21:22 GMT+0200 (CEST)

I can't figure out what could cause it to behave in the manner you described though. Maybe someone else can help you with that.

ago by (100 points)
I'm not sure exactly what part of the code I had was wrong- I recopied the widget that was posted above and replaced what I had, and it's working now.
Welcome to Twine Q&A, where you can ask questions and receive answers from other members of the community.

You can also find hints and information on Twine on the official wiki and the old forums archive.

See a spam question? Flag it instead of downvoting. A question flagged enough times will automatically be hidden while moderators review it.